使用 const 变量作为非类型模板参数

use*_*729 0 c++ c++11

我有一个关于使用const变量作为模板参数的问题。

使用 gcc 和 clang x64 trunk可以很好地编译以下内容:

template <int N>
void func() { }

int main(int argc, char *argv[]) { 
    const int x = 12;
    func<x>();
}
Run Code Online (Sandbox Code Playgroud)

然而,正如人们所预料的那样,这个版本main()无法编译:

int main(int argc, char *argv[]) { 
    const int x = argc;
    func<x>();
}
Run Code Online (Sandbox Code Playgroud)

不应该x被要求吗constexpr?或者,当该值可以在编译时确定时,是const隐式的吗?constexpr

use*_*522 5

通常,如果您想在常量表达式中使用变量的值(即在编译时求值中),则必须对变量进行标记,constexpr正如模板参数所要求的那样。

但是,整型和枚举类型有一个例外const,假设它们本身是用常量表达式初始化的,也允许以这种方式使用它们。

在第一个示例中,x使用常量表达式初始化。在你的第二个例子中,它显然不是(因为argc是函数参数)。

这种例外是有历史原因的。在发明之前就已经可以以const这种方式使用积分/枚举变量constexpr(首次出现在 C++11 中)。如果没有这样的规则,在 C++11 之前就没有任何方法可以提供命名的非类型模板参数或数组边界,除非通过预处理器宏(如没有 VLA 的 C 的情况)。而且,由于新的 C++ 版本不应该对旧代码造成不必要的破坏,因此该异常仍然存在。