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?
decltype(auto)
, returningint&
works Demo or evenauto&
Demo. – Excavatorint&& r = 1; decltype(auto) rr = (r);
. Live demo: godbolt.org/z/jWzEadYsW. – Theis*&r
). – Heterosexual