This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 113d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-03-20


1454. Passing constants through constexpr functions via references

Section: 7.7  [expr.const]     Status: CD3     Submitter: Richard Smith     Date: 2011-12-27

[Moved to DR at the October, 2012 meeting.]

The current wording incorrectly appears to make the following example ill-formed:

   constexpr const int &f(const int &n) { return n; }
   constexpr int k = f(0);   // ill-formed

Proposed resolution (February, 2012):

  1. Change 7.7 [expr.const] paragraph 2 as follows:

  2. A conditional-expression is a core constant expression unless it involves one of the following...

  3. Change 7.7 [expr.const] paragraph 3 as follows, dividing it into two paragraphs:

  4. A literal constant expression is a prvalue core constant expression of literal type, but not pointer type. An integral constant expression is a literal constant an expression of integral or unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression. [Note: Such expressions may be used as array bounds (9.3.4.5 [dcl.array], 7.6.2.8 [expr.new]), as bit-field lengths (11.4.10 [class.bit]), as enumerator initializers if the underlying type is not fixed (9.7.1 [dcl.enum]), as null pointer constants (7.3.12 [conv.ptr]), and as alignments (9.12.2 [dcl.align]). —end note] A converted constant expression of type T is a literal constant an expression, implicitly converted to a prvalue of type T, where the implicit conversion (if any) is permitted in a literal converted expression is a core constant expression and the implicit conversion sequence contains only user-defined conversions, lvalue-to-rvalue conversions (7.3.2 [conv.lval]), integral promotions (7.3.7 [conv.prom]), and integral conversions (7.3.9 [conv.integral]) other than narrowing conversions (9.4.5 [dcl.init.list]). [Note: such expressions may be used as case expressions (8.5.3 [stmt.switch]), as enumerator initializers if the underlying type is fixed (9.7.1 [dcl.enum]), and as integral or enumeration non-type template arguments (13.4 [temp.arg]). —end note]

    A literal constant expression is a prvalue core constant expression of literal type, but not pointer type (after conversions as required by the context). For a literal constant expression of array or class type, each subobject of its value shall have been initialized by a constant expression. A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function. An address constant expression is a prvalue core constant expression (after conversions as required by the context) of type std::nullptr_t or of pointer type that evaluates to the address of an object with static storage duration, to the address of a function, or to a null pointer value, or a prvalue core constant expression of type std::nullptr_t. Collectively, literal constant expressions, reference constant expressions, and address constant expressions are called constant expressions.

  5. Change the second example 9.2.6 [dcl.constexpr] paragraph 5 as follows:

  6.   constexpr int f(bool b)
        { return b ? throw 0 : 0; }                  // OK
      constexpr int f() { throw 0 return f(true); }  // ill-formed, no diagnostic required
      ...
    

This resolution also resolves issue 1455.