constexpr函数参数作为模板参数

时间:2014-10-27 07:36:04

标签: c++ c++11 constexpr

我正在玩一些使用c ++ 11的玩具代码,以更多地了解事情的运作方式。在此期间,我遇到了以下问题,简化为:

template <int x, int y>
class add {
public:
    static constexpr int ret = x + y;
};

constexpr int addFunc(const int x, const int y) {
    return add<x,y>::ret;
}

int main() {
    const int x = 1;
    const int y = 2;
    cout << add<x,y>::ret << endl; // Works
    cout << addFunc(1,2) << endl;  // Compiler error
    return 0;
}

我正在使用GCC 4.8.1,输出是:
'x'不是类型'int'的模板参数中的常量表达式 'y'不是类型'int'

的模板参数中的常量表达式

我尝试计算add::ret的两种方式之间究竟有什么区别?这两个值都应该在编译时可用。

4 个答案:

答案 0 :(得分:10)

如果你的目的只是缩短代码,在C ++ 14中你可以创建变量模板:

template <int x, int y>
constexpr int addVar = x + y;

cout << addVar<5, 6> << endl; // Works with clang 3.5, fails on GCC 4.9.1

GCC 5 will also support this

答案 1 :(得分:10)

你告诉编译器,addFunc将是一个constexpr。但它依赖于参数,而不是constexpr本身,所以编译器已经扼杀了它。将它们标记为const仅表示您不会在函数体中修改它们,并且此时不会考虑对函数进行的特定调用。

有一种方法可以让编译器理解你只是将编译时常量传递给addFunc:使参数本身成为模板参数:

template <int x, int y>
constexpr int addFunc() {
    return add<x,y>::ret;
}

然后打电话给

cout << addFunc<1,2>() << endl;

答案 2 :(得分:7)

编译器不知道x和y在编译时是否始终可用作常量值(表达式),而且 C ++ 11/14不支持constexpr函数参数,所以x和y无法用作模板add&lt;&gt;的参数。在addFunc。

答案 3 :(得分:4)

constexpr函数的函数参数不是常量表达式。该函数向外constexpr(因为调用它可能会导致常量表达式),但内部计算与正常函数中的constexpr一样。

Template-arguments需要常量表达式。这些是代码中不满足的常量表达式的关键要求,从而产生编译器错误([expr.const] / 2,强调我的):

  

条件表达式核心常量表达式,除非它   涉及以下之一作为潜在评估的子表达式   (3.2)[...]:

     

- 左值 - 右值转换(4.1),除非它适用于

     
      
  • 一个整数或枚举类型的glvalue,它引用一个带有前面初始化的非易失性const对象,已初始化   使用常量表达式
  •   
  • 一个文字类型的glvalue,它指的是用constexpr 定义的非易失性对象,或者指的是这样的子对象   对象,或
  •   
  • 一个文字类型的glvalue,指的是一个非易失性临时对象,其生命周期尚未结束,用一个常量初始化   表达
  •   

您正在对参数应用左值到右值转换,以将它们作为模板参数传递。
第一个项目不适用,因为函数参数既没有先前初始化也不知道用常量表达式初始化,第二个和第三个项目也没有(特别是函数参数应该是不要声明constexpr)。