C++ 编译时数组常量

C++ 编译时数组常量,c++,templates,standards,compile-time-constant,C++,Templates,Standards,Compile Time Constant,我似乎遗漏了一些相当基本的东西。 我试图在编译时使用常量数组成员 const int list[3] = { 2, 5, 7 }; const int a = list[2]; // this doesn't error? template<int N1, int N2> struct tmax { enum { value = ((N1 > N2) ? N1 : N2) }; }; const int b = tmax<2,4>::value; const

我似乎遗漏了一些相当基本的东西。 我试图在编译时使用常量数组成员

const int list[3] = { 2, 5, 7 };
const int a = list[2]; // this doesn't error?

template<int N1, int N2>
struct tmax {
  enum { value = ((N1 > N2) ? N1 : N2) };
};

const int b = tmax<2,4>::value;
const int c = tmax<list[0],list[1]>::value; // error is here

int main()
{
  return 0;
}
这是你的电话号码


那么为什么这不起作用呢?我错过了什么?我应该怎么做呢?

仅仅因为一个对象是
const
并不意味着它是一个编译时常量表达式

main.cpp:10:20: error: non-type template argument is not a constant expression
const int c = tmax<list[0],list[1]>::value; // error is here
                   ^~~~~~~
main.cpp:10:20: note: read of non-constexpr variable 'list' is not allowed in a constant expression
main.cpp:1:11: note: declared here
const int list[3] = { 2, 5, 7 };
          ^
constexpr int list[3] = { 2, 5, 7 };
const int a = list[2];
至于为什么会这样做:

const int a = list[2]; // this doesn't error?
初始化
const
变量不需要常量表达式:

int foo(int n) {
    const int a = n; // initializing const var with a non-compile time constant
如果表达式包含多个不允许的子表达式中的任何一个,则表达式不是常量表达式。其中一类不允许的子表达式是:

  • 左值到右值的转换(4.1),除非应用于
    • 整数或枚举类型的glvalue,它引用具有前一个 初始化,使用常量表达式初始化,或
    • 一种文本类型的glvalue,它引用用
      constexpr
      定义的非易失性对象,或引用 该对象的子对象,或
    • 一个文本类型的glvalue,它引用一个非易失性临时对象,该对象的生存期尚未结束 结束,用常量表达式初始化
特别是,虽然使用常量初始值设定项初始化的enum或Integral类型的常量对象的名称形成常量表达式(读取其值是导致左值到右值转换的原因),但常量聚合对象的子对象(例如示例中的
list
,数组)不会,但是如果声明为
constexpr

const int list[3] = { 2, 5, 7 };
const int a = list[2];
这是有效的,但是
a
不构成常量表达式,因为它不是用常量表达式初始化的

main.cpp:10:20: error: non-type template argument is not a constant expression
const int c = tmax<list[0],list[1]>::value; // error is here
                   ^~~~~~~
main.cpp:10:20: note: read of non-constexpr variable 'list' is not allowed in a constant expression
main.cpp:1:11: note: declared here
const int list[3] = { 2, 5, 7 };
          ^
constexpr int list[3] = { 2, 5, 7 };
const int a = list[2];
通过更改
list
的声明(我们不必更改
a
的声明),我们可以使
a
形成一个常量表达式

main.cpp:10:20: error: non-type template argument is not a constant expression
const int c = tmax<list[0],list[1]>::value; // error is here
                   ^~~~~~~
main.cpp:10:20: note: read of non-constexpr variable 'list' is not allowed in a constant expression
main.cpp:1:11: note: declared here
const int list[3] = { 2, 5, 7 };
          ^
constexpr int list[3] = { 2, 5, 7 };
const int a = list[2];

由于
list[2]
现在是一个常量表达式,
a
现在是一个用常量表达式初始化的整数类型的
const
对象,因此
a
现在可以用作常量表达式。

我认为constexpr会有所帮助,现在我看到它的使用范围比我想象的要广。话虽如此,对于为什么const int a的声明有效,而list[1]具体无效,我们希望能多做一点解释。谢谢。好的,VisualStudio2012不打算支持constexpr。有没有其他解决办法?我不必使用它,但它会很好。@std''OrgnlDave我添加了更多的编译器诊断,这正好解释了列表[1]不是常量表达式的原因。visual studio 2k12不支持constexpr几乎让我哭了。我从未在模板元编程中使用过这样的数组,但我很期待它。。。
main.cpp:10:20: error: non-type template argument is not a constant expression
const int c = tmax<list[0],list[1]>::value; // error is here
                   ^~~~~~~
main.cpp:10:20: note: read of non-constexpr variable 'list' is not allowed in a constant expression
main.cpp:1:11: note: declared here
const int list[3] = { 2, 5, 7 };
          ^
constexpr int list[3] = { 2, 5, 7 };
const int a = list[2];