2

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{});
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • 2
    The `a` parameter is not a *prvalue*, it is an *lvalue*, hence why the cast fails. – Remy Lebeau Apr 03 '20 at 01:44
  • @RemyLebeau Thanks, please see my edited question – xskxzr Apr 03 '20 at 02:01
  • @RemyLebeau lvalue may be implicitly converted to prvalue – M.M Apr 03 '20 at 02:56
  • I looked at this yesterday as someone asked where lvalue conversion might occur for class types; if non-pointer types are similar then `T t; const_cast(t)` would be an example (which would materialize a temporary) – M.M Apr 03 '20 at 03:18

1 Answers1

1

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 that T is

“cv0 P0 cv1 P1 ··· cvn-1 Pn-1 cvn Ufor 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.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Interesting, [the current draft allows n=0](https://timsong-cpp.github.io/cppwp/conv.qual#1). It seems like there is a core language issue covering this. – xskxzr Apr 03 '20 at 03:16