C++标准下将xvalue作为lvalue返回的代码合法性判定
结论
你编写的原始代码是完全符合C++标准的合法代码,GCC 11.2的报错属于该版本的编译器bug,GCC 12及以上版本已经修复了该问题。
原理说明
- 核心规则铺垫
- 右值引用类型的变量本身是左值:只要是有名字、可以取地址的变量,哪怕它的类型是右值引用,它作为表达式时的值类别都是左值
decltype作用于带括号的左值表达式时,推导结果是左值引用:对于类型为T的左值表达式,decltype(表达式)的结果为T&decltype(auto)作为返回类型时,会直接用decltype(return 后的表达式)推导实际的返回类型
代码合法性推导
当你调用RtoL(std::move(x))时,泛型lambda的auto&&参数会推导为int&&,即参数r的类型是int&&;return (r)中的(r)是左值表达式,decltype((r))的推导结果是int&,因此lambda的实际返回类型是int&;
左值r完全可以合法绑定到左值引用返回类型int&,代码没有任何语法或语义违规。GCC 11.2报错的原因
该版本的GCC在处理泛型lambda的decltype(auto)返回类型推导时存在逻辑bug,错误地将返回类型推导为了参数的右值引用类型int&&,才会抛出「无法将int左值绑定到int&&右值引用」的错误提示,该判定不符合C++标准要求。关于修改后代码的说明
你将return语句改为return static_cast<decltype(r)&&>(r);后,返回的表达式是int&&类型的xvalue,decltype推导得到的返回类型也是int&&,自然所有编译器都不会报错,但此时返回值是右值,和你原本「接收右值返回左值」的设计目标完全不符。
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

