Date
2024-10-25.20:21:22
Message id
7851

Content

Proposed resolution (approved by CWG 2024-10-25)

  1. Change in 7.2.1 [basic.lval] paragraph 7 as follows:

    Whenever Unless otherwise specified (7.6.1.11 [expr.const.cast]), whenever a prvalue appears as an operand of an operator that expects a glvalue for that operand, the temporary materialization conversion (7.3.5 [conv.rval]) is applied to convert the expression to an xvalue.
  2. Change in 7.6.1.11 [expr.const.cast] paragraph 1 as follows:

    The result of the expression const_cast<T>(v) is of type T. If T is an lvalue reference to object type, the result is an lvalue; if T is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue and the lvalue-to-rvalue (7.3.2 [conv.lval]), array-to-pointer (7.3.3 [conv.array]), and function-to-pointer (7.3.4 [conv.func]) standard conversions are performed on the expression v. The temporary materialization conversion (7.3.5 [conv.rval]) is not performed on v, other than as specified below. Conversions that can be performed explicitly using const_cast are listed below. No other conversion shall be performed explicitly using const_cast.
  3. Change in 7.6.1.11 [expr.const.cast] paragraph 3 as follows:

    For two similar object pointer or pointer to data member types T1 and T2 (7.3.6 [conv.qual]), a prvalue of type T1 may can be explicitly converted to the type T2 using a const_cast if, considering the qualification-decompositions of both types, each Pi1 is the same as Pi2 for all i. The result of a const_cast refers to the original entity. If v is a null pointer or null member pointer, the result is a null pointer or null member pointer, respectively. Otherwise, the result points to or past the end of the same object, or points to the same member, respectively, as v. [Example 1:
      typedef int *A[3];                // array of 3 pointer to int
      typedef const int *const CA[3];   // array of 3 const pointer to const int
      CA &&r = A{};        // OK, reference binds to temporary array object
                           // after qualification conversion to type CA
      A &&r1 = const_cast<A>(CA{});     // error: temporary array decayed to pointer
    
      A &&r2 = const_cast<A&&>(CA{});    // OK
    
    -- end example]
  4. Change in 7.6.1.11 [expr.const.cast] paragraph 4 as follows:

    For two object types T1 and T2, if a pointer to T1 can be explicitly converted to the type “pointer to T2” using a const_cast, then the following conversions can also be made:
    • an lvalue of type T1 can be explicitly converted to an lvalue of type T2 using the cast const_cast<T2&>;
    • a glvalue of type T1 can be explicitly converted to an xvalue of type T2 using the cast const_cast<T2&&>; and
    • if T1 is a class or array type, a prvalue of type T1 can be explicitly converted to an xvalue of type T2 using the cast const_cast<T2&&>. The temporary materialization conversion is performed on v.
    The result of a reference const_cast refers to the original same object if as the (possibly converted) operand is a glvalue and to the result of applying the temporary materialization conversion (7.3.5 [conv.rval]) otherwise.

    [Example 2:

      typedef int *A[3];                // array of 3 pointer to int
      typedef const int *const CA[3];   // array of 3 const pointer to const int
    
      auto &&r2 = const_cast<A&&>(CA{}); // OK, temporary materialization conversion is performed
    

    -- end example]

  5. Remove 7.6.1.11 [expr.const.cast] paragraph 5:

    A null pointer value (6.8.4 [basic.compound]) is converted to the null pointer value of the destination type. The null member pointer value (7.3.13 [conv.mem]) is converted to the null member pointer value of the destination type.
  6. Change in 9.5.4 [dcl.init.ref] bullet 5.3 as follows:

    [Example 5: ...
      constexpr int f() {
        const int &x = 42;
        const_cast<int &>(x) = 1;  // undefined behavior
        return x;
      }
      constexpr int z = f();          // error: not a constant expression
    
      typedef int *AP[3];        // array of 3 pointer to int
      typedef const int *const ACPC[3]; // array of 3 const pointer to const int
      ACPC &&r = AP{};          // binds directly
    
    -- end example]

This resolution also resolve issue 1965.