仅移动类型返回到转换构造函数

时间:2017-09-07 13:37:41

标签: c++ language-lawyer move-semantics rvalue

以下代码返回一个只迁移类型,然后由转换构造函数转换为另一种类型。

,

这使我的编译器出错,只能通过将,添加到被认为是不良做法的return语句来修复,因为通常它会阻止返回值优化。不应该首先将return语句的标识符视为rvalue以满足转换吗?

此代码是否有效以及哪个编译器就在这里?

2 个答案:

答案 0 :(得分:4)

  

不应该首先将return语句的标识符视为rvalue以满足转换吗?

是和否。 [class.copy]的结果来自CWG 1579(此处的措辞是从C ++ 17中复制的,虽然它在C++14中是相同的。我发现子弹比早期的语法更容易阅读让詹姆斯乔伊斯脸红的选择......):

  

在以下复制初始化上下文中,可能会使用移动操作而不是复制操作:

     
      
  • 如果return语句中的表达式是一个(可能带括号的)id-expression,它指定一个对象,该对象具有在最内层封闭函数或lambda-expression的body或parameter-declaration-clause中声明的自动存储持续时间,或
  •   
  • [...]
  •   
     首先执行

重载决策以选择复制的构造函数,就好像该对象是由rvalue指定的一样。如果第一个重载决策失败或未执行,或如果所选构造函数的第一个参数的类型不是对象类型的右值引用(可能是cv-qualified),则执行重载决策再次,将对象视为左值。

第一个项目符号适用于此处,因此我们首先执行重载解析,就像foo是右值一样。这是通过Other(Foo )Foo(Foo&& )构造函数的。

Other(Foo )的第一个参数不是右值引用,因此我们应该再次进行重载解析,将foo视为左值,这会失败。这似乎是一个不必要的限制,但我在这里打电话给clang是正确的。如果将构造函数更改为Other(Foo&& ),则clang接受它。

答案 1 :(得分:2)

巴里的好答案涵盖了标准规则,但我有一个实际的建议:

  

并且只能通过将std::move添加到被认为是不良做法的return语句来修复,因为通常它会阻止返回值优化。

你的担心是没有道理的。 NRVO无论如何都不适用于转换,并允许RVO对移动结果。明确的举动很好。