26

According to [expr.cast]/4, a C-style cast tries the following casts in order:

  1. const_cast
  2. static_cast
  3. static_cast followed by const_cast
  4. reinterpret_cast
  5. reinterpret_cast followed by const_cast

The following cast is well-formed:

const_cast<int&>(static_cast<const int&>(0))

Yet both GCC and Clang reject the cast (int&)0. Why?

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • What would you want it to mean? –  Mar 30 '18 at 21:50
  • 1
    @NeilButterworth I'm not saying it should be well-formed; I'm saying the rules of the language appear to make it well-formed and I would like someone to point out the error in my reasoning. – Brian Bi Mar 30 '18 at 21:50
  • UPDATE: The first (well-formed) cast was not rejected by Clang on my machine. The second cast was rejected. Hmm. Making it a `const int&` it was not rejected. I'll have to ponder. – Eljay Mar 30 '18 at 21:53
  • @Justin • I had updated my comment. I cut-n-pasted the first (good) casts. – Eljay Mar 30 '18 at 21:56
  • 1
    @Eljay Casting to `const int&` is fine because of lifetime extension – Justin Mar 30 '18 at 21:56
  • 1
    @Peter I disagree that this is a duplicate of that question. This question is focused around why the C-style cast doesn't succeed, not around why the `const&` works – Justin Mar 30 '18 at 21:59
  • 3
    Reopen-hammered :) – Brian Bi Mar 30 '18 at 22:00
  • 1
    You might as well ask why `static_cast0` is rejected by the compiler, because that is what `(int &)0` resolves to. And the question I linked to as a dup addresses that. – Peter Mar 30 '18 at 22:04
  • 4
    @Peter No, that's not how it works. The compiler will accept `float* p; (int*)p;` even though the static cast would be rejected---because it interprets it as a reinterpret cast instead. But in my case, the (third) alternative interpretation is not used. – Brian Bi Mar 30 '18 at 22:05
  • I think this question shows the same bugs that your previous one showed. So in a way it's a duplicate. – Sebastian Redl Mar 30 '18 at 22:30
  • @SebastianRedl However, I'm not sure whether the committee would agree that this case (as opposed to the previous one) is supposed to be well-formed. Perhaps a wording change is needed. – Brian Bi Mar 30 '18 at 22:33
  • @Brian - I concur about the wording change. Hopefully to something that doesn't leave it open to "interpretation" (pun intended). – StoryTeller - Unslander Monica Mar 30 '18 at 22:39
  • I posted to std-discussion@isocpp.org – Brian Bi Mar 30 '18 at 22:46
  • In that context, the ampersand `&` creates an alias to (the name of) an lvalue. The number 0 is not a name or an lvalue. – Jive Dadson Mar 30 '18 at 23:35
  • It says the first fashion from that list in which the cast “can be interpreted [...] is used, even if a cast resulting from that interpretation is ill-formed”. I suppose the interpretation as a bare `static_cast` is considered “possible” until [expr.static.cast]/1 forbids that it “cast away constness”. But that would seem to prevent ever using interpretation #3. – Davis Herring Mar 31 '18 at 01:59
  • Related, and possible duplicate: [r-value Reference Casting and Temporary Materialization](https://stackoverflow.com/questions/48796854/r-value-reference-casting-and-temporary-materialization/48939852#comment84928372_48939852) – xskxzr Mar 31 '18 at 09:39
  • Possible duplicate of [r-value Reference Casting and Temporary Materialization](https://stackoverflow.com/questions/48796854/r-value-reference-casting-and-temporary-materialization) – stands2reason Apr 11 '18 at 16:05
  • Related/possible duplicate: https://stackoverflow.com/questions/66816741/why-does-this-c-style-cast-not-consider-static-cast-followed-by-const-cast – user17732522 Mar 01 '22 at 18:06

1 Answers1

4

It is a bug in gcc and clang.

According to CWG 909, the "straightforward interpretation of the wording" should be used when generating cast sequences for C-style casts; there, the first cast invokes a conversion operator, but there is no reason to think that it should be any different when the first cast is reference binding a temporary.

I've posted a patch to the gcc mailing list, generated from this git branch, but it hasn't received any attention so far.

ecatmur
  • 152,476
  • 27
  • 293
  • 366