简体   繁体   English

编译时数组常量

[英]Compile-time array constants

I seem to be missing something rather fundamental. 我似乎错过了一些相当基本的东西。 I'm trying to use const array members at compile-time. 我正在尝试在编译时使用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;
}

Errors: 错误:

prog.cpp:10:24: error: 'list' cannot appear in a constant-expression
prog.cpp:10:30: error: an array reference cannot appear in a constant-expression

Here is the relevent IDEOne link 这是相关的IDEOne链接

So why doesn't this work? 那么为什么这不起作用呢? What am I missing? 我错过了什么? What should I do differently? 我该怎么办?

Just because an object is const doesn't mean it's a compile time constant expression. 仅仅因为对象是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 };
          ^

This is the reason for constexpr : 这是constexpr的原因:

constexpr int list[3] = { 2, 5, 7 };

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; // works fine now

As for why this works: 至于为什么这样做:

const int a = list[2]; // this doesn't error?

initializing a const variable doesn't require a constant expression: 初始化const变量不需要常量表达式:

int foo(int n) {
    const int a = n; // initializing const var with a non-compile time constant

Expressions are not constant expressions if they contain any one of a number of disallowed sub-expressions. 如果表达式包含许多不允许的子表达式中的任何一个,则表达式不是常量表达式。 One such class of disallowed sub-expressions is: 一类这样的不允许的子表达式是:

  • an lvalue-to-rvalue conversion (4.1) unless it is applied to 除非适用,否则左值到右值的转换(4.1)
    • a glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression, or 一个整数或枚举类型的glvalue,它引用一个带有前面初始化的非易失性const对象,用一个常量表达式初始化,或者
    • a glvalue of literal type that refers to a non-volatile object defined with constexpr , or that refers to a sub-object of such an object, or 一个文字类型的glvalue,它指的是用constexpr定义的非易失性对象,或者指的是这样一个对象的子对象,或者
    • a glvalue of literal type that refers to a non-volatile temporary object whose lifetime has not ended, initialized with a constant expression; 一个文字类型的glvalue,它引用一个生命周期尚未结束的非易失性临时对象,用一个常量表达式初始化;

In particular, while the name of a const object of enum or intergral type initialized with a constant initializer forms a constant expression (reading its value is what causes the lvalue-to-rvalue conversion), sub-objects of an const aggregate object (such as list in your example, an array) do not, but would if declared constexpr . 特别是,使用常量初始化程序初始化的枚举或整数类型的const对象的名称形成一个常量表达式 (读取其值是导致左值到右值转换的原因),const聚合对象的子对象(如如你的例子中的list ,数组)不,但如果声明constexpr

const int list[3] = { 2, 5, 7 };
const int a = list[2];

This is valid but a does not constitute a constant expression because it is not initialized with a constant expression . 这是有效的但是a不构成常量表达式,因为它没有用常量表达式初始化。

By changing the declaration of list (we don't have to change the declaration of a ), we can make a form a constant expression. 通过改变的申报list (我们没有改变的声明a ),我们可以做a形式的常量表达式。

constexpr int list[3] = { 2, 5, 7 };
const int a = list[2];

As list[2] is now a constant expression , a is now a const object of intergral type initialized with a constant expression so a can now be used as a constant expression. list[2]现在是一个常量表达式a现在是一个const与一个常量表达式所以初始化可积型的对象a现在可以用作常量表达式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM