Is the following C++11 program ill-formed?
const int x[] = {1,2,3};
static_assert(x[0] == 1, "yay");
int main() {}
gcc and clang seem to think so, but why isn't x[0] == 1
a constant expression?
x[0] == 1
subscript operator
*(x+0) == 1
array-to-pointer conversion (int* p = x)
*(p+0) == 1
pointer addition
*p == 1
indirection (lvalue y = x[0])
y == 1
lvalue-to-rvalue conversion:
a non-volatile glvalue (yes, x[0] is a glvalue and non-volatile) of integral (yes it has type const int) or enumeration type that refers to a non-volatile const object (yes it has type const int) with a preceding initialization (yes initialized with 1), initialized with a constant expression (yes 1 is constant expression)
Seems true, the first element of the x
array satisfies these conditions.
1 == 1
?
Is this a compiler bug, standard defect, or am i missing something?
What part of 5.19 [expr.const] says this isn't a constant expression?
A constant expression is an expression that can be fully evaluated at compile time. Therefore, the only possible values for constants of reference types are string and a null reference. The constant declaration can declare multiple constants, such as: C# Copy.
A constant value is one that doesn't change. C++ provides two keywords to enable you to express the intent that an object is not intended to be modified, and to enforce that intent. C++ requires constant expressions — expressions that evaluate to a constant — for declarations of: Array bounds.
Yes, you can use them together.
In 5.19:
A [...]expression is a constant expression unless it involves one of the following [...]:
an lvalue-to-rvalue conversion (4.1) unless it is applied to
- 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 initialized with a constant expression
Putting it plainly, lvalue-to-rvalue conversion can only be done in constant expressions if:
const int x = 3;
.constexpr
: constexpr int x[] = {1,2,3};
.Your example does include lvalue-to-rvalue conversion, but has none of these exceptions, so x
is not a constant expression. If, however, you change it to:
constexpr int x[] = {1,2,3};
static_assert(x[0] == 1, "yay");
int main() {}
Then all is well.
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