【问题标题】:int p is not a constant expression in lpNorm<p>int p 不是 lpNorm<p> 中的常量表达式
【发布时间】:2016-07-14 18:05:42
【问题描述】:

这个函数是我写的

    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

我该如何解决这个问题?

【问题讨论】:

  • 模板在编译时解析...

标签: c++ c++11 eigen


【解决方案1】:

您可以在有限的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;
  }
}

【讨论】:

  • 出于好奇,我们能否使用一些模板魔法生成等效的开关?
  • 更具体一点,我的意思是在编译时将采用通用函子和std::integer_sequence 的可能值,并生成必要的管道以根据运行时值进行选择。
  • @lisyarus 没错。这将非常方便,谢谢!
【解决方案2】:

模板在编译时解析。正因为如此,它们不能是运行时变量。尽管参数声明中的const p 仍然是一个运行时变量。

参数声明中的const 仅表示函数不能更改参数值。仍然可以使用普通的非常量变量调用您的函数。

【讨论】:

    【解决方案3】:

    你不能。

    模板在编译时解析。这意味着对于lpNorm&lt;p&gt;() 行中p 的每个值,您将生成特定于该模板的代码。如果p 可以是任何值,那么您需要为每个可能的值生成代码,这不是一个好主意,编译器会告诉您这一点。

    p 必须在编译时已知,这意味着您需要执行以下操作:

    template <int p, typename T>
    double norm(const T & v) {
    

    然后专门针对您可能希望收到的任何p 值。

    如果p 确实是动态的,那么您需要一个运行时解决方案,而不是编译时解决方案,因此您可能想要这样:

    lpNorm(p);
    

    (您显然需要重新定义 lpNorm 的工作方式)

    【讨论】:

    • p 设为第一个模板参数会更有意义。
    猜你喜欢
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多