C++ constexpr函数参数作为模板参数

C++ constexpr函数参数作为模板参数,c++,c++11,constexpr,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() { co

我正在玩一些使用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;
}
模板
类添加{
公众:
静态constexpr int ret=x+y;
};
常量表达式int addFunc(常量int x,常量int y){
返回add::ret;
}
int main(){
常数int x=1;
常数y=2;

cout编译器不知道x和y在编译时是否始终作为常量值(表达式)可用,而且,C++11/14不支持constexpr函数参数,因此无法将x和y用作模板外接程序addFunc的参数。

如果您的目的只是稍微缩短代码,则可以在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
模板
constexpr int addVar=x+y;

您是否可以告诉编译器,
addFunc
将是一个constexpr。但是它依赖于参数,而不是constexpr本身,因此编译器已经对此感到窒息。将它们标记为const只意味着您不打算在函数体中修改它们,此时不考虑您对函数的特定调用。

有一种方法可以让编译器明白,您只需将编译时常量传递给
addFunc
:将参数设置为模板参数本身:

template <int x, int y>
constexpr int addFunc() {
    return add<x,y>::ret;
}
模板
constexpr int addFunc(){
返回add::ret;
}
那就叫

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

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

模板参数需要常量表达式。这些是代码中未满足的常量表达式的关键要求,因此会产生编译器错误([expr.const]/2,emphasis mine):

条件表达式是核心常量表达式,除非 作为可能的求值子表达式涉及以下内容之一 (3.2)[……]:

-左值到右值的转换(4.1),除非应用于

  • 整型或枚举型的glvalue值,它引用具有先前初始化的非易失性常量对象,已初始化 使用常量表达式,
  • 一种文本类型的glvalue值,它引用由constexpr定义的非易失性对象,或引用此类对象的子对象 反对,或
  • 一种文本类型的glvalue,它引用一个非易失性的临时对象,该对象的生存期尚未结束,并用常量初始化 表达方式
您正在对参数应用从左值到右值的转换,以将其作为模板参数传递。

第一个项目符号项不适用,因为函数参数既不是预先初始化的,也不是已知的用常量表达式初始化的,第二个和第三个项目符号项也不适用(特别是,函数参数不应声明为
constexpr
)ME常数,所以您的<代码> COSTEXPROP>代码>函数无效。您所寻找的不是“代码> CONExPRP</代码>提供的,也不是C++提供的另一种形式。最接近的是,用<代码> int x< /代码>和<代码> int y < /COD>模板参数来创建<>代码>模板函数。尽管在编译时进行了计算,但它们在运行时也必须是有效的?哈哈,这样做本质上是想找到一种避免使用宏的方法。我想这就是它必须要做的。