This is some kind of follow-up for this topic and deals about a little part of it. As with the previous topic, let\'s consider that our compiler has constexpr
funct
I figured out what is going on here:
constexpr std::initializer_list b = { a[0], a[1], a[2] };
a[0]
of type const int&
implicitly converts to a temporary of type const int
.
Then g++ converts it to const int*
to pass into the initializer_list
private constructor.
In the last step it takes address of a temporary, so it is not a constant expression.
The problem is in implicit conversion to const int. Example:
constexpr int v = 1;
const int& r = v; // ok
constexpr int& r1 = v; // error: invalid initialization of reference of
// type ‘int&’ from expression of type ‘const int’
The same behavior is in clang.
I think this conversion is legal, nothing says the opposite.
About const int&
to const int
conversion, [expr] paragraph 5:
If an expression initially has the type “reference to T” , the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression.
The result of a[0]
expression is the temporary xvalue of type const int
in that case.
About implicit conversions in constexpr initializer, [dcl.constexpr] paragraph 9:
... 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.
About taking address of temporary, [expr.const] paragraph 2:
...an invocation of a constexpr function with arguments that, when substituted by function invocation substitution, do not produce a constant expression; [ Example:
constexpr const int* addr(const int& ir) { return &ir; } // OK static const int x = 5; constexpr const int* xp = addr(x); // OK: (const int*)&(const int&)x is an // address contant expression constexpr const int* tp = addr(5); // error, initializer for constexpr variable // not a constant expression; // (const int*)&(const int&)5 is not a // constant expression because it takes // the address of a temporary
— end example ]