C++ 如何在“上进行类型转换”;隐式;return语句中的rvalue
这是无效的吗?gcc接受,clang和msvc不接受C++ 如何在“上进行类型转换”;隐式;return语句中的rvalue,c++,language-lawyer,C++,Language Lawyer,这是无效的吗?gcc接受,clang和msvc不接受 #include <memory> class Holder { std::unique_ptr<int> data; public: operator std::unique_ptr<int>() && { return std::move(data); } }; std::unique_ptr<int> test() { Holder val;
#include <memory>
class Holder {
std::unique_ptr<int> data;
public:
operator std::unique_ptr<int>() && { return std::move(data); }
};
std::unique_ptr<int> test()
{
Holder val;
return val;
}
#包括
阶级持有者{
std::唯一的ptr数据;
公众:
运算符std::unique_ptr()&&{return std::move(data);}
};
标准::唯一性测试()
{
持有者val;
返回val;
}
假设我不想添加类似std::unique_ptr Holder::TakeData(){return std::move(data);}
,我唯一能想到的其他解决方法是在返回值中移动:
std::unique_ptr<int> test()
{
Holder val;
return std::move(val); // lets the conversion proceed
}
std::unique_ptr test()
{
持有者val;
return std::move(val);//让转换继续进行
}
但是gcc 9.3+却厚颜无耻地告诉我,std::move
是冗余的(启用了所有警告)。世界跆拳道联盟?我的意思是,是的,gcc
不需要移动,当然,但是其他任何东西都不接受代码。如果不是gcc,那么一些人以后不可避免地会对此犹豫不决
TakeData
函数限制为右值上下文,即必须执行返回std::move(val).TakeData()
运算符std::unique_ptr()&{return std::move(data);}
不是一个选项,因为它显然会导致严重的错误-它可以在错误的上下文中调用。标准要求进行“隐式”右值转换。但根据您使用的标准版本,哪种编译器是“正确的”是不同的
在C++17中
[class.copy.elision](强调我的)
在以下复制初始化上下文中,移动操作
可能用于替代复制操作:
- 如果return语句中的表达式是用automatic命名对象的id表达式(可能带括号) 在body或parameter声明子句中声明的存储持续时间 最里面的封闭函数或lambda表达式,或
val
作为右值应该无法初始化返回类型,因为我用粗体标记了一个句子(在unique\u ptr
C'tor中的右值引用不直接绑定到val
),但在C++20中,这个句子就不存在了
C++20
隐式可移动实体是自动存储的变量
非易失性对象或右值引用的持续时间
到非易失性对象类型。在以下复制初始化中
在上下文中,可以使用移动操作而不是复制操作:
- 如果return([stmt.return])或coreturn([stmt.return.coroutine])语句中的表达式是(可能带括号) id表达式,该表达式命名在 最里面的封闭表达式的body或parameter声明子句 函数或lambda表达式,或
- [……]
std::unique_ptr<int> test()
{
Holder val;
std::unique_ptr<int> ret_val = std::move(val);
return ret_val;
}
std::unique_ptr test()
{
持有者val;
std::unique_ptr ret_val=std::move(val);
返回返回值;
}
我从一开始就同意,这看起来可能不像简单地返回val
那么吸引人,但至少它在NRVO中起到了很好的作用。因此,我们不太可能获得比最初期望的更多的unique\u ptr
如果这仍然太不吸引人,那么我觉得你关于窃取资源的成员函数的想法最符合我的喜好。但是没有考虑品味。我认为答案是肯定的,但措辞在我看来毫无意义。