将 xvalue 作为左值呈现的有效性

Enr*_*lis 11 c++ language-lawyer move-semantics xvalue c++17

以下函数(按照我的意图)是获取右值并将其呈现为左值。

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

我考虑在我可以保证 xvalue 没有真正被移动的情况下使用它(例如,它通过 转换为右值std::move,但没有利用它),所以我会用 xvalues 来调用它,而不是纯右值。

不管怎样,编译器(好吧,GCC 的版本)似乎对上面代码的有效性有不同的看法。具体来说,考虑到这种用法:

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

GCC 11.2 认为它无效:

int main() {
    int x{3};
    RtoL(std::move(x));
}
Run Code Online (Sandbox Code Playgroud)

而 GCC 10.3 和其他编译器认为它是有效的。

此外,将 return 语句从

return (r);
Run Code Online (Sandbox Code Playgroud)

return static_cast<decltype(r)&>(r);
Run Code Online (Sandbox Code Playgroud)

让他们都同意代码是正确的。

从标准的角度来看,真相在哪里?

ein*_*ica 2

这是 GCC 过去版本中的一个错误(由评论者 @Enlico 发现)

该错误已由 GCC 版本 12.2 修复,但在 GCC 11.3 中仍然存在。它也可能会在 GCC 11.4 中得到修复。

请参阅此GodBolt