From [expr.const.cast]/3:
For two similar types T1 and T2, a prvalue of type T1 may be explicitly converted to the type T2 using a const_cast if, considering the cv-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.
It seems that const cast to non-pointer non-reference type is allowed. For example, the following function
void f(int a)
{
const_cast<int>(a);
}
should be well-formed, since int
and int
are certainly similar types and have no Pi in their cv-decompositions (thus the proposition that "each Pi1 is the same as Pi2 for all i" should be true).
However, both GCC and Clang reject the code above (see Compiler Explorer). The error messages are
Clang:
<source>: In function 'void f(int)':
<source>:3:22: error: invalid use of const_cast with type 'int', which is not a pointer, reference, nor a pointer-to-data-member type
3 | const_cast<int>(a);
| ^
GCC:
<source>: In function 'void f(int)':
<source>:3:5: error: invalid use of 'const_cast' with type 'int', which is not a pointer, reference, nor a pointer-to-data-member type
3 | const_cast<int>(a);
| ^~~~~~~~~~~~~~~~~~
Am I missing something or is it a compiler bug?
UPDATE: this doesn't work, either:
void f()
{
const_cast<int>(int{});
}
In C++17 the types are not similar so the quoted text doesn't apply. And so this const_cast
is not allowed because no const_cast
is allowed unless explicitly permitted.
C++17 [conv.qual]/1:
A cv-decomposition of a type
T
is a sequence of cvi and Pi such thatT
is“cv0 P0 cv1 P1 ··· cvn-1 Pn-1 cvn
U
” for n > 0,where each cvi is a set of cv-qualifiers (6.9.3), and each Pi is “pointer to” (11.3.1), “pointer to member of class Ci of type” (11.3.3), “array of Ni ”, or “array of unknown bound of” (11.3.4). [...]
and then
Two types T1 and T2 are similar if they have cv-decompositions with the same n such that corresponding Pi components are the same and the types denoted by
U
are the same.
The requirement n > 0 means that there must be cv0 P0, i.e. at least one pointer in the type.
The latest C++20 draft changes n > 0 to n ≥ 0, as a result of Issue 2051. But makes no change to the specification of const_cast
. I couldn't say whether this is intentional or an oversight.
So it may be that C++20 will make your const_cast
expressions well-defined , and compilers will have to catch up.