12

Can someone explain why both compilers throw an error on the second example whereas only gcc throws an error on the first example? Is it somehow related to the result of the static_cast being an xvalue?

int& example1 = reinterpret_cast<int&>(static_cast<int&&>(10));
//(gcc 10.2) error: invalid cast of an rvalue expression of type 'int' to type 'int&'
//(clang 11.0.0) no errors

int& example2 = reinterpret_cast<int&>(10);
//(gcc 10.2) error: invalid cast of an rvalue expression of type 'int' to type 'int&'
//(clang 11.0.0) error: reinterpret_cast from rvalue to reference type 'int &'

Also I'm not sure but I think the first example is well-formed because according to the standard, an xvalue is a type of a glvalue, right? And this [expr.reinterpret.cast]/11 part of the standard says that I should be able to cast T1 glvalues to the type “reference to T2” with the T1 being the same type as T2 in this case.

  • 5
    A compiler variance is pretty good for a first question to stackoverflow. – Sam Varshavchik Nov 18 '20 at 12:00
  • Just a guess, but misusing `reinterpret_cast` might just not require any diagnostics? – lubgr Nov 18 '20 at 12:04
  • @Surt I removed it again, because results seem to be inconsistent. When I reload the page gcc randomly reports the error or not. Hre is my link again https://godbolt.org/z/48rqds – 463035818_is_not_an_ai Nov 18 '20 at 12:20
  • @Surt I saw all gcc versions i tested report the error, now I see 3 out of 5 versions report the error and before I had only 1 out of the 5 report the error. All that just by reloading the page. The issue seems to be more interesting than I first assumed – 463035818_is_not_an_ai Nov 18 '20 at 12:22
  • @lubgr So, I'm not really sure but I think it's not a misuse because according to the standard, an xvalue is a type of a glvalue, right? And this https://eel.is/c++draft/expr.reinterpret.cast#11 part of the standard says that I should be able to cast T1 glvalues to the type “reference to T2” with the T1 being the same type as T2 in this case. But then again, I'm definitely not sure so I'd be glad if someone could back this claim of mine. –  Nov 18 '20 at 12:25
  • @SnakePin perhaps add that to your question. Comments are easily overlooked and are not permanent, they can vanish at any time – 463035818_is_not_an_ai Nov 18 '20 at 12:28
  • @idclev463035818 This is brilliant!! I reloaded that demo 5 times, and got at least 4 different results :) – cigien Nov 18 '20 at 12:29
  • I've edited in your comment since it's relevant, and a posted answer already refers to that. – cigien Nov 18 '20 at 12:51
  • @LanguageLawyer I think we should close this as a dupe to the Q&A you proposed. – dfrib Nov 18 '20 at 14:48
  • @dfrib But the body of the question is more like about why `reinterpret_cast(10)` is ill-formed :D – Language Lawyer Nov 18 '20 at 14:49
  • 2
    @LanguageLawyer Yes possibly that was a bit confusing, but from the comments to my answer it seems OP actually was more interested in `reinterpret_cast(std::move(10));`; I guess it doesn't hurt to have these two Q&A:s connected by a dupe link :) – dfrib Nov 18 '20 at 14:51
  • 1
    @dfrib I've edited the question's body and title, is it more clear now? –  Nov 18 '20 at 15:09
  • @LanguageLawyer By the way, quite unrelated but you said "an xvalue is a type of a glvalue No." but the standard certainly says that an xvalue is a glvalue https://timsong-cpp.github.io/cppwp/basic.lval#1.3. I'm sure you know this but I think there's been a misunderstanding. –  Nov 18 '20 at 15:19
  • Misread as "rvalue is a glvalue". – Language Lawyer Nov 18 '20 at 15:29

1 Answers1

3
reinterpret_cast<int&>(10);

This program is ill-formed, as the expression being converted from is a prvalue. From [expr.reinterpret.cast]/1:

The result of the expression reinterpret_­cast<T>(v) is the result of converting the expression v to type T. If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; [...] Conversions that can be performed explicitly using reinterpret_­cast are listed below. No other conversion can be performed explicitly using reinterpret_­cast.

None of the clauses that follows allows a reinterpret_cast from a (p)rvalue that is not a pointer.


#include <memory>
reinterpret_cast<int&>(std::move(10));

Here, the expression being converted from is an xvalue, and as shown in the Q&A linked to in a comment by @LanguageLawyer (which is arguably a dupe target for this Q&A)

this is well-formed, as of C++14 (updated as a DR fix also to C++11) and the actual implementation of CWG 1268:

1268. reinterpret_cast of an xvalue operand Section: 8.2.10 [expr.reinterpret.cast]

Status: CD3

Submitter: Michael Wong

Date: 2011-03-21

[Moved to DR at the October, 2012 meeting.]

8.2.10 [expr.reinterpret.cast] paragraph 11, dealing with casting to reference types, only allows an lvalue operand. Presumably it should allow a glvalue operand when the target is an rvalue reference type.

[...]

Note that the emphasized segment proposes to allow this only when the target is an rvalue reference, but the actually updated [expr.reinterpret.cast]/11 removed this restriction.

Consequently, GCC is wrong to reject the first example.

dfrib
  • 70,367
  • 12
  • 127
  • 192
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/224763/discussion-on-answer-by-dfrib-why-are-the-compiler-errors-inconsistent-in-gcc-an). – Samuel Liew Nov 19 '20 at 02:35