int p不是lpNorm <p>中的常量表达式

时间:2016-07-14 18:05:42

标签: c++ c++11 eigen

我写了这个函数

    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

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:3)

你不能。

模板在编译时解析。这意味着对于行plpNorm<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;
  }
}