The changes in this document are primarily to broaden the allowance to non-const references. Any problematic operation on a non-const reference is still prohibited because it would prevent the function body from being a potential constant expression.
7.1.5/4, first bullet:
- its return type shall be a literal type or a reference to literal type
- each of its parameter types shall be a literal type or a reference to literal type
5.19/2, third bullet:
- each of its parameter types shall be a literal type or a reference to literal type
5.19/2, bullets 6-9:
- an
direct or indirectinvocation of an undefined constexpr function or an undefined constexpr constructor outside the definition of a constexpr function or a constexpr constructor;- an invocation of a constexpr function with arguments that, when implicitly converted to the corresponding parameter types and substituted for the corresponding parameters in the potential constant expression of the constexpr function, and the resulting expression implicitly converted to the return type, 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 constant 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 ]
5.19/6:
- 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 variable 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;
[ Footnote: The temporary must be part of the constant expression, as any longer-lived temporary would have to be bound to a reference, and reference variables cannot appear in a constant expression --end footnote]- an array-to-pointer conversion (4.2) that is applied to a glvalue that does not designate
san object with staticthread or automaticstorage duration;- a unary operator & (5.3.1) that is applied to an lvalue that does not designate
san object with staticthread or automaticstorage duration;- 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 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. --end footnote ];
An expression is a potential constant expression if it is a constant expression when all occurrences of function parameters are replaced as follows:7.1.5:
- 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; or
- for rvalue reference parameters, by arbitrary prvalue constant expressions of the referred-to types implicitly converted to the types of the parameters.
If the instantiated template specialization of a constexpr function template would fail to satisfy the requirements for a constexpr function or constexpr constructor, the constexpr specifier is ignored.A call to a constexpr function produces the same result as a call to an equivalent non-constexpr function in all respects except that a call to a constexpr function can appear in a constant expression.