Consider the following code:
constexpr const int A = 42;
const int &B = A;
static_assert(&A == &B, "Bug");
constexpr const int &C = B;
static_assert(&A == &C, "Bug");
int main() { return 0; }
It is perfectly accepted by clang version 3.3, whereas g++ (SUSE Linux) 4.8.1 20130909 [gcc-4_8-branch revision 202388 refuses it with:
bug2.cpp:5:1: error: non-constant condition for static assertion
static_assert(&A == &B, "Bug");
^
bug2.cpp:5:1: error: the value of ‘B’ is not usable in a constant expression
bug2.cpp:2:12: note: ‘B’ was not declared ‘constexpr’
const int &B = A;
^
It seems to me that GCC is correct (whereas I certainly would prefer clang behavior). Trying to read the standard I realized that I'm not enough of a language lawyer to decide. Can anyone confirm that?
the value of ‘B’ is not usable in a constant expression
is incorrect. You are not performing an lvalue-to-rvalue conversion on B, which is the usual meaning of "value;" you are only taking its address. The only relevant constant-expression rule forbids:
an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization, initialized with a constant expression;
However B
does have a preceding initialization to a reference constant expression.
A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function.
In this case, B
's initializer is A
, which is as constant as you can get. A
and B
statically refer to the same object.
So, this is a GCC bug.
Without being a language lawyer, you cannot use a reference as a constant expression in general, only values (if there are exceptions please correct me). In this sense, the closest valid to your code would be:
constexpr int A = 42;
constexpr int B = A;
static_assert(A == B, "Bug");
However, in my case, both Clang 3.3 and GCC 4.8.1 give errors on your code as expected.
EDIT Apparently my knowledge is still a bit narrow, sorry. There are probably exceptions depending on linkage, for instance the code is accepted (live) if the statements are global, outside main()
.
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