11

The following function (in my intention) is to take an rvalue and present it as it was an lvalue.

auto constexpr RtoL = [](auto&& r) -> decltype(auto) {
    static_assert(std::is_rvalue_reference_v<decltype(r)>, "Gimme rvalues, not lvalues.");
    return (r);
};

I think of using it in situations where I can guarantee that an xvalue has not been truly moved from (e.g. it was casted to rvalue via std::move, but nothing took advantage of that), so I'd call it with xvalues, not prvalues.

Anyway, compilers (well, versions of GCC) seem to have different opinions on the validity of the code above. Specifically, given this usage:

int main() {
    int x{3};
    RtoL(std::move(x));
}

GCC 11.2 considers it invalid:

<source>:9:14: error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'
    9 |     return (r);
      |              ^

whereas GCC 10.3 and other compilers consider it valid.

Furthermore, changing the return statement from

return (r);

to

return static_cast<decltype(r)&>(r);

makes them all agree that the code is correct.

Where is the truth, from the standard standpoint?

Enlico
  • 23,259
  • 6
  • 48
  • 102
  • 1
    Gcc seems to have issue with `decltype(auto)`, returning `int&` works [Demo](https://godbolt.org/z/48jK4s4f4) or even `auto&` [Demo](https://godbolt.org/z/Yhq3qff3M). – Jarod42 Nov 24 '21 at 08:47
  • Possibly minimal exemplary code with the same issue: `int&& r = 1; decltype(auto) rr = (r);`. Live demo: https://godbolt.org/z/jWzEadYsW. – Daniel Langr Nov 24 '21 at 08:57
  • Relevant (possibly duplicate): [GCC's decltype(auto) doesn't conform to the standard?](https://stackoverflow.com/q/53358751/580083). – Daniel Langr Nov 24 '21 at 08:59
  • @DanielLangr, following the like you posted, I could get [here](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78209), where I read _fixed in GCC 11_, but the version where I observe the problem is exactly GCC 11.2. Should I deduce that the bug has been reintroduced? Do you suggest filing another report? – Enlico Nov 24 '21 at 09:22
  • @Enlico I am not a Bugzilla expert, but I guess yes, it seems that the problem has not been fixed as advertized. – Daniel Langr Nov 24 '21 at 09:26
  • [Reported](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103403). – Enlico Nov 25 '21 at 15:54
  • Note that C++23 will [require the cast](https://open-std.org/JTC1/SC22/WG21/docs/papers/2022/p2266r3.html) (or `*&r`). – Davis Herring Aug 27 '22 at 19:44

1 Answers1

2

This was a bug in past versions of GCC (located by commenter @Enlico)

The bug is fixed by GCC version 12.2, but still manifests with GCC 11.3. It will likely be fixed in GCC 11.4 as well.

See this on GodBolt.

einpoklum
  • 118,144
  • 57
  • 340
  • 684