Title
Undesired outcomes with const_cast
Status
open
Section
7.6.1.11 [expr.const.cast]
Submitter
Brian Bi

Created on 2024-04-15.00:00:00 last changed 2 weeks ago

Messages

Date: 2024-04-18.22:29:47

Suggested resolution:

  1. 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.
  2. 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 member, respectively, as v.
  3. 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 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.
  4. 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.
Date: 2024-04-18.22:29:47

Suggested resolution [SUPERSEDED]:

  1. Change in 7.6.1.11 [expr.const.cast] paragraph 3 as follows:

    For two similar types T1 and T2 (7.3.6 [conv.qual]), a prvalue of type T1 may 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 T is an object pointer type or pointer to data member type, the type of v shall be similar to T and the corresponding Pi components of the qualification decompositions of T and the type of v shall be the same (7.3.6 [conv.qual]). 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 member, respectively, as v.

    [ Example: ... ]

  2. 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 type, a prvalue of type T1 can be explicitly converted to an xvalue of type T2 using the cast const_cast<T2&&>.

    The result of a reference const_cast refers to the original object if the operand is a glvalue and to the result of applying the temporary materialization conversion (7.3.5 [conv.rval]) otherwise.

    Otherwise, T shall be a reference type. Let T1 be the type of v and T2 be the type referred to by T. A const_cast from "pointer to T1" to "pointer to T2" shall be valid. If T is an lvalue reference type, v shall be an lvalue. Otherwise, if T2 is a class type and v is a prvalue, the temporary materialization conversion (7.3.5 [conv.rval]) is applied. Otherwise, the temporary materialization conversion is not applied and v shall be a glvalue. The result refers to the same object as the (possibly converted) operand.

  3. 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.
Date: 2024-04-16.12:41:05

(From submissions #526, #232, and #342.)

The resolution of issue 891 intended to make const_cast<int&&>(2) ill-formed. However, combined with the temporary materialization conversion turning prvalues into glvalues (7.1 [expr.pre] paragraph 7, this is now well-formed.

Also, the current rules regrettably allow const_cast<int>(0) and const_casts involving function pointers and pointers to member functions. The latter is non-normatively considered disallowed by the note in 7.6.1.11 [expr.const.cast] paragraph 9.

Major implementations except MSVC agree with the proposed direction of this issue.

History
Date User Action Args
2024-04-18 22:29:47adminsetmessages: + msg7667
2024-04-16 07:22:48adminsetmessages: + msg7666
2024-04-15 00:00:00admincreate