Change in 3.6.2 basic.start.init paragraph 2 as indicated:
Constant initialization is performed:Change in 5.19 expr.const paragraph 2:
- ...
- if an object with static or thread storage duration is initialized
such that the initialization satisfies the requirements for the object being declared with constexpr (7.1.5 dcl.constexpr).by a constructor call, if the constructor is a constexpr constructor, if all constructor arguments are constant expressions (including conversions), and if, after function invocation substitution (7.1.5 dcl.constexpr), every constructor call and full-expression in the mem-initializers is a constant expression- if an object with static or thread storage duration is not initialized by a constructor call and if every full-expression that appears in its initializer is a constant expression.
Remove 5.19 expr.const paragraph 6 entirely:
- an invocation of a function other than a constexpr constructor for a literal class or a constexpr function
or a constexpr constructor[ Note: overload resolution (13.3) is applied as usual -- end note ];- ...
- an invocation of a
constexpr
function with arguments that, when substituted by function invocation substitution (7.1.5 dcl.constexpr)implicitly converted to the corresponding parameter types and substituted for the corresponding parameters in the potential constant expression of the, do not produce a constant expression; [ Example:constexpr
function, and the resulting expression implicitly converted to the return typeconstexpr 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]- an invocation of a
constexpr
constructor with arguments that, when substituted by function invocation substitution (7.1.5 dcl.constexpr), do not produce all constant expressions for the constructor calls and full-expressions in the mem-initializers; [ Example:int x; // not constant struct A { constexpr A(bool b) : m(b ? 42 : x) { } int m; }; constexpr int v = A(true).m; // ok, constructor call initializes // m with the value 42 after substitution constexpr int w = A(false).m; // error: initializer for m is // "x", which is non-constant]- ...
- an id-expression that refers to a variable or data member of reference type; [ Footnote: Use of a reference parameter of a
constexpr
function does not prevent the function from being used in constant expressions, because function invocation substitution will replace the parameters with the argument expressions.body from being a potential constant expression because the parameters are replaced by constant expressions during that determination, and later by arguments to a call.]- ...
Change in 7.1.5 dcl.constexpr paragraph 3 as indicated:An expression is a potential constant expression if it is a constant expression when all occurrences of function parameters are replaced as follows:
for non-reference parameters, by arbitrary prvalue constant expressions of the appropriate types;for lvalue reference parameters, by arbitrary variables of the referred-to types with static storage duration initialized with constant expressions; orfor rvalue reference parameters, by arbitrary prvalue constant expressions of the referred-to types implicitly converted to the types of the parameters.
Change 7.1.5 dcl.constexpr paragraph 4 as indicated:[ Example: ... ]
- its function-body shall be a compound-statement of the form
{ return expression ; }where expression is a potential constant expression (5.19 expr.const)
In 7.1.5 dcl.constexpr, add a new paragraph after the current paragraph 4:A trivial copy/move constructor is also a
every constructor argument and full-expression in a mem-initializer shall be a potential constant expressionconstexprconstexpr
constructor. [ Example: ... ]
Function invocation substitution for a call of aChange 7.1.5 dcl.constexpr paragraph 8 as indicated:constexpr
function or of aconstexpr
constructor means to convert implicitly each argument expression to the corresponding parameter type as if by copy-initialization [ Footnote: The resulting converted value will include an lvalue-to-rvalue conversion (4.1 conv.lval) if the corresponding copy-initialization requires one. --end footnote], to substitute that converted expression for each use of the corresponding parameter in the function-body, and, for constexpr functions, to convert implicitly the resulting expression to the return type of the function. Such substitution does not change the meaning. [ Example:constexpr int f(void *) { return 0; } constexpr int f(...) { return 1; } constexpr int g1() { return f(0); } // calls f(void *) constexpr int g2(int n) { return f(n); } // calls f(...) even for n == 0 constexpr int g3(int n) { return f(n*0); } // calls f(...) namespace N { constexpr int c = 5; constexpr int h() { return c; } } constexpr int c = 0; constexpr int g4() { return N::h(); } // value is 5, "c" is not looked up again after the substitution] For a constexpr function, if no function argument values exist such that the function invocation substitution would produce a constant expression (5.19 expr.const), the program is ill-formed; no diagnostic required. For a constexpr constructor, if no argument values exist such that after function invocation substitution, every constructor call and full-expression in the mem-initializers would be a constant expression (including conversions), the program is ill-formed; no diagnostic required. [ Example:constexpr int f(bool b) { return b ? throw 0 : 0; } // ok constexpr int f() { throw 0; } // ill-formed, no diagnostic required struct B { constexpr B(int x) : i(0) { } // "x" is unused int i; }; int global; struct D : B { constexpr D() : B(global) { } // ill-formed, no diagnostic required // lvalue-to-rvalue conversion on non-constant "global" };]
Aconstexpr
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,the constructor shall be athat call shall be a constant expression (5.19 expr.const). Otherwise, 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 expr.const). [ Example:constexpr
constructor and every argument to the constructor shall be a constant expressionstruct pixel { int x, y; }; constexpr pixel ur = { 1294, 1024 };// OK constexpr pixel origin; // error: initializer missing]