Consider this example from 7.6.1.10, paragraph 3 [expr.const.cast] (N4810):
typedef int *A[3]; // array of 3 pointer to int
typedef const int *const CA[3]; // array of 3 const pointer to const int
...
A &&r2 = const_cast<A&&>(CA{}); // OK
So, the standard says it's a legitimate code, but
none of
g++-7
orclang-6
compiles fine.In fact, this
const_cast
-related comments fromllvm
states:.... if (isa<RValueReferenceType>(DestTypeTmp) && SrcExpr.get()->isRValue()) { if (!SrcType->isRecordType()) { // Cannot const_cast non-class prvalue to rvalue reference type. But if // this is C-style, static_cast can do this. msg = diag::err_bad_cxx_cast_rvalue; return TC_NotApplicable; } // Materialize the class prvalue so that the const_cast can bind a // reference to it. NeedToMaterializeTemporary = true; } ...
This basically says that we can't materialize(=cast) a non-class prvalue to a xvalue.
Also, the same paragraph from which the above example originates says:
For two similar types
T1
andT2
, a prvalue of typeT1
may be explicitly converted to the typeT2
using aconst_cast
. The result of aconst_cast
refers to the original entity.Compare this to the one right after it (7.6.1.10, paragraph 4 [expr.const.cast]):
For two object types
T1
andT2
, if a pointer toT1
can be explicitly converted to the type “pointer toT2
” using aconst_cast
, then the following conversions can also be made:- an lvalue of type
T1
can be explicitly converted to an lvalue of typeT2
using the castconst_cast<T2&>
; - a glvalue of type
T1
can be explicitly converted to an xvalue of typeT2
using the castconst_cast<T2&&>
; and - if
T1
is a class type, a prvalue of typeT1
can be explicitly converted to an xvalue of typeT2
using the castconst_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 otherwise.
This contrast seems to insinuate that, a cast from a non-class prvalue to a xvalue won't suffer temporary materialization conversion, which looks odd to me.
- an lvalue of type
Then, what's the intention of the example above?
const_cast
refers to the original entity This wording is clearly defective, because in C++17 and above prvalues do not denote entities. – Tryckconst int*
toint*
, where the resulting value points to the same entity as the original value. – Mog