Is the code fragment
struct Parameters {
static constexpr int n = 2;
static constexpr double v[n] = {4.0, 5.0};
};
legal C++11? And, if so, are Parameters::v[0]
and Parameters::v[1]
compile time constants or is just the pointer Parameters::v
itself a constexpr
(whatever that would mean at compile time)?
As you can see I am generally a bit confused about constexpr
arrays and their initialization in classes/structs. Please feel free to not only answer my specific question but also to mention common pitfalls and the like concerning this topic.
I see no problem with the construct. Quoting C++11, [dcl.constexpr]
:
§1 The
constexpr
specifier shall be applied only to the definition of a variable, the declaration of a function or function template, or the declaration of a static data member of a literal type (3.9). ...§9 A
constexpr
specifier used in an object declaration declares the object asconst
. Such an object shall have literal type and shall be initialized. If it is initialized by a constructor call, that call shall be a constant expression (5.19). Otherwise, or if a constexpr specifier is used in a reference declaration, every full-expression that appears in its initializer shall be a constant expression. Each implicit conversion used in converting the initializer expressions and each constructor call used for the initialization shall be one of those allowed in a constant expression (5.19).
double
is a literal type, and so is an array of literal types. Which means that v[0]
and v[1]
from your code are indeed constant expressions.
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;
}
This code on gcc 4.8.2 compiles into the following:
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
So yes, it is a compile time constant.
clang 3.4 produces similar code:
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
Again, it is a compile time constant.
Everything was compiled with -O0.
P.S.: If a is declared const, then for gcc nothing changes but for clang does, the value 4 is not mov'ed directly as if was a compile time constant.
If a is declared neither const or constexpr then both compilers fail to treat Parameters::v[0] as a compile time constant.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With