c++ - 返回到转换构造函数中的仅 move 类型

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

以下代码返回一个只能 move 的类型,然后应通过转换构造函数将其转换为另一种类型。

#include <utility>

class Foo
{
public:
  Foo() {}
  Foo(const Foo&) = delete;
  Foo(Foo&&) = default;
};

class Other
{
public:
  Other(Foo foo) {}
};


Other moo()
{
  Foo foo;
  return foo;
}

int main()
{
  moo();
}

这给我的编译器带来了一个错误,只能通过将 std::move 添加到 return 语句来修复,这被认为是不好的做法,因为通常它会阻止返回值优化。难道不应该首先将 return 语句的标识符视为右值以满足转换吗?

这段代码有效吗?哪个编译器就在这里?

最佳答案

Shouldn't the identifier of a return statement be treated as rvalue first to satisfy conversions?

是也不是。来自 [class.copy] , 由于 CWG 1579 (这里的措辞是从 C++17 复制而来的,尽管它在 C++14 中是相同的。我发现项目符号比早期的语法选择更容易阅读,这会让 James Joyce 脸红...):

In the following copy-initialization contexts, a move operation might be used instead of a copy operation:

  • If the expression in a return statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, or
  • [...]

overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If the first overload resolution fails or was not performed, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object's type (possibly cv-qualified), overload resolution is performed again, considering the object as an lvalue.

第一条适用于此,因此我们首先进行重载解析,就好像 foo 是右值一样。这是通过 Foo(Foo&& ) 获取到 Other(Foo ) 构造函数。

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

关于c++ - 返回到转换构造函数中的仅 move 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46097854/

相关文章:

C++ 异常和 .eh_frame ELF 部分

c++ - 编译链接 x86 静态库的 x64 动态库时的 LNK2001 和 LNK1120

c++ - 如果 T1 和 T2 有, std::pair<T1,T2> 不应该有微不足道的默认构造函数吗?

c++ - 是否有任何关于为什么重新定义枚举器格式错误的规则?

c++ - unordered_map 没有匹配的调用错误

c - 在 C 中同时创建内部和外部链接

c++ - 成员函数 .begin() 和 std::begin()

c++ - 我可以列表初始化一个只 move 类型的 vector 吗?

c++ - 不可 move -不可复制对象的 vector 的 move 分配不编译

c++ - 在 .m 和 .mm 文件中调用 .cpp 函数,错误