Description
Full name of submitter: Brian Bi
Reference (section label): [expr.const.cast]
Issue description: There are a few issues here.
The current specification allows constructs like const_cast<int>(0)
and const_cast
s involving function pointers and pointers to member functions, but this is probably unintentional, and no implementations accept them. We need to say that a cast to object type is allowed only if the object type is an object pointer or pointer to data member type.
"The result of a const_cast
refers to the original entity" in paragraph 3 is wrong; it should say "points". Also, the sentence about null pointers is 2 paragraphs down, which is odd.
CWG891, adopted for C++11, made const_cast<int&&>(2)
illegal. However, [expr]/7 now says:
Whenever a prvalue appears as an operand of an operator that expects a glvalue for that operand, the temporary materialization conversion is applied to convert the expression to an xvalue.
and [expr.const.cast]/4.2 says:
a glvalue of type
T1
can be explicitly converted to an xvalue of typeT2
using the castconst_cast<T2&&>
[...]
Taken together, this implies that const_cast<int&&>
expects a glvalue operand, so a prvalue can be materialized to produce the expected glvalue, which contradicts the intent.
Also, the resolution of CWG891 for some reason treats class prvalues and array prvalues unequally. We may want to fix this. The suggested resolution below leaves the current behavior alone, but it would be easy to amend it if we want a change in this area.
Suggested resolution:
Strike the last two sentences from [expr.const]/1:
The result of the expression const_cast(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, array-to-pointer, and function-to-pointer standard conversions are performed on the expression v.
Conversions that can be performed explicitly using const_cast are listed below. No other conversion shall be performed explicitly using const_cast.
Replace the text in [expr.const]/3 with the following, leaving the examples:
If
T
is an object pointer type or pointer to data member type, the type ofv
shall be similar toT
and the corresponding P_i components of the qualification decompositions ofT
and the type ofv
shall be the same ([conv.qual]). Ifv
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, asv
.
Replace [expr.const]/4 with:
Otherwise,
T
shall be a reference type. LetT1
be the type ofv
andT2
be the type referred to byT
. Aconst_cast
from "pointer toT1
" to "pointer toT2
" shall be valid. IfT
is an lvalue reference type,v
shall be an lvalue. Otherwise, ifT2
is a class type andv
is a prvalue, the temporary materialization conversion ([conv.rval]) is applied. Otherwise, the temporary materialization conversion is not applied andv
shall be a glvalue. The result refers to the same object as the (possibly converted) operand.
Strike [expr.const]/5:
A null pointer value ([basic.compound]) is converted to the null pointer value of the destination type.
The null member pointer value ([conv.mem]) is converted to the null member pointer value of the destination type.