首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >编译时数组常量

编译时数组常量
EN

Stack Overflow用户
提问于 2012-06-10 07:10:48
回答 2查看 3.1K关注 0票数 11

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

代码语言:javascript
复制
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;
}

错误:

代码语言:javascript
复制
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

这是relevent IDEOne link

那么,为什么这不起作用呢?我遗漏了什么?我应该采取不同的做法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-10 07:18:04

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

代码语言:javascript
复制
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的原因

代码语言:javascript
复制
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

至于为什么这是可行的:

代码语言:javascript
复制
const int a = list[2]; // this doesn't error?

初始化const变量不需要常量表达式:

代码语言:javascript
复制
int foo(int n) {
    const int a = n; // initializing const var with a non-compile time constant
票数 9
EN

Stack Overflow用户

发布于 2012-06-10 07:35:51

如果表达式包含许多不允许的子表达式中的任何一个,则它们不是常量表达式。这样一类不允许的子表达式是:

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

代码语言:javascript
复制
- 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  
- 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  
- a glvalue of literal type that refers to a non-volatile temporary object whose lifetime has not   ended, initialized with a constant expression;

特别是,使用常量初始化器初始化的枚举或整数类型的常量对象的名称会形成一个常量表达式(读取它的值会导致左值到右值的转换),而常量聚合对象的子对象(如本例中的list,一个数组)不会形成常量表达式,但如果声明为constexpr,就会形成常量表达式。

代码语言:javascript
复制
const int list[3] = { 2, 5, 7 };
const int a = list[2];

这是有效的,但a不构成常量表达式,因为它不是用常量表达式初始化的。

通过更改list的声明(我们不必更改a的声明),我们可以使a形成常量表达式。

代码语言:javascript
复制
constexpr int list[3] = { 2, 5, 7 };
const int a = list[2];

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

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10965241

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档