constexpr数组成员是否编译时间常量
Are constexpr array members compile time constants?
是代码片段
struct Parameters {
static constexpr int n = 2;
static constexpr double v[n] = {4.0, 5.0};
};
合法的C++11?如果是,Parameters::v[0]
和Parameters::v[1]
是编译时常数,还是指针Parameters::v
本身就是constexpr
(无论在编译时意味着什么(?
正如您所看到的,我通常对constexpr
数组及其在类/结构中的初始化有点困惑。请不仅回答我的具体问题,而且提及与此主题相关的常见陷阱等。
我认为构造没有问题。引用C++11,[dcl.constexpr]
:
§1
constexpr
说明符应仅适用于变量的定义、函数的声明或函数模板,或文字类型(3.9(的静态数据成员的声明…§9对象声明中使用的
constexpr
说明符将对象声明为const
。此类对象应具有文字类型,并且应进行初始化。如果它是由构造函数调用初始化的,则该调用应为常量表达式(5.19(。否则,或者如果在引用声明中使用了constexpr说明符,则每个完整表达式出现在其初始值设定项中的应该是一个常量表达式。中使用的每个隐式转换转换初始值设定项表达式,用于初始化的每个构造函数调用都应该是在常数表达式(5.19(中允许。
double
是一个文字类型,文字类型的数组也是如此。这意味着代码中的v[0]
和v[1]
实际上是常量表达式。
struct Parameters {
static constexpr int n = 2;
static constexpr double v[n] = {4.0, 5.0};
};
int main() {
constexpr int a = Parameters::v[0];
return 0;
}
gcc 4.8.2上的这段代码编译成以下代码:
0000000000000000 <main>:
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: c7 45 fc 04 00 00 00 mov DWORD PTR [rbp-0x4],0x4
b: b8 00 00 00 00 mov eax,0x0
10: 5d pop rbp
11: c3 ret
是的,它是一个编译时常数。
clang 3.4产生类似的代码:
0000000000000000 <main>:
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: b8 00 00 00 00 mov eax,0x0
9: c7 45 fc 00 00 00 00 mov DWORD PTR [rbp-0x4],0x0
10: c7 45 f8 04 00 00 00 mov DWORD PTR [rbp-0x8],0x4
17: 5d pop rbp
18: c3 ret
同样,它是一个编译时常数。
所有内容都是用-O0编译的。
附言:如果a被声明为const,那么对于gcc,除了clang之外什么都没有改变,值4不会像编译时常量一样直接被mov'ed。
如果既没有声明const也没有声明constexpr,则两个编译器都无法将Parameters::v[0]视为编译时常数。
struct Parameters {
static constexpr int n = 2;
static constexpr double v[n] = {4.0, 5.0};
};
据我所知,这个片段本身当然是合法的。C++11标准的7.1.5节[dcl.constexpr]说
constexpr说明符应仅应用于…文字类型的静态数据成员的声明
并且文字类型在3.9:中定义
如果类型是:,则该类型为文字类型
--标量类型;或
--文字类型的数组
因此,就我所知,static constexpr double v[2] = { ... }
当然是有效的。
至于数组的成员是否为constexpr
。。。我不确定。如果我们申报
constexpr double d = Parameter::v[1];
然后g++和clang都可以编译它,但clang版本无法链接到未定义的Parameters::v
引用。我不知道这是否指向Clang错误,或者该构造是否无效。
- C++为构建时间获取QDateTime的可靠方法
- #定义c-预处理器常量..我做错了什么
- 从持续时间构造std::chrono::system_clock::time_point
- C++常量数组的编译时间较长
- 如何在 c++ stl 中获取列表中被推回的元素的地址,在常量时间内?
- 具有静态存储持续时间的常量初始化变量的初始化顺序
- std::unordered_set 是否对任何对象进行摊销常量查找时间,而不考虑谓词
- 在不同翻译单元中具有静态存储持续时间的依赖非局部常量浮点变量的常量初始化
- 对列表中的任意元素的常量时间访问 (C++)
- vector::size() 如何在常量时间内返回向量的大小
- 常量时间更改数组的前 k 个元素(C++)
- 在常量时间内表达单向链表方法:O(1)
- 插入号码的常量时间查找
- NVIDIA NVCC 在使用模板特征类型时更改编译时间常量
- 使用递归在常量空间和线性时间中向后打印链表
- 提升::p osix_time::p时间来自常量字符* "substring"
- ' const int a = 1; '是' a '一个常量表达式,如果' a '具有自动存储持续时间
- constexpr数组成员是否编译时间常量
- 是dynamic_cast常量时间
- 常量时间std::list将大小调整为给定的最后一个元素