我写了这个函数
template <typename T>
double norm(const T & v, const int p) {
return v.template lpNorm<p>();
}
但它不起作用并给出错误:
error: 'p' is not a constant expression
return v.template lpNorm<p>();
^
我似乎认为编译器希望在编译时知道p
,而我的p
是动态的。
可能相关:
Why is this not a constant expression?
Non-type template argument is not a constant expression
我该如何解决这个问题?
答案 0 :(得分:3)
模板在编译时解析。这意味着对于行p
中lpNorm<p>()
的每个值,您将生成特定于该模板的代码。如果p
可以是任何值,那么您需要为每个可能的值生成代码,这不是一个好主意,编译器会告诉您这一点。
p
,这意味着您需要执行以下操作:
template <int p, typename T>
double norm(const T & v) {
然后专门针对您可能希望收到的p
的任何值。
如果p
真的是动态的,那么你需要一个运行时解决方案,而不是编译时解决方案,所以很可能你想要这个:
lpNorm(p);
(您显然需要重新定义lpNorm
的工作方式)
答案 1 :(得分:3)
模板在编译时解析。因此,它们不能成为运行时变量。尽管参数声明const
中的p
仍然是运行时变量。
参数声明中的const
只表示函数不能更改参数值。仍然可以使用普通的非常量变量调用函数。
答案 2 :(得分:3)
您可以使用有限范围的p
部分执行此操作。对于lpNorm
操作,通常就足够了。
您已经知道需要编译时常量作为模板参数。但是,由于p
通常用于小范围(0,1,2,inf),因此您可以使用以下技巧使其适用于常用int
值的小子集。
template<typename T>
double norm(const T & v, const int p) {
switch (p) {
case 0:
return v.template lpNorm<0>();
break;
case 1:
return v.template lpNorm<1>();
break;
case 2:
return v.template lpNorm<2>();
break;
case Eigen::Infinity:
return v.template lpNorm<Eigen::Infinity>();
break;
default:
break;
}
}