能否将不可移动不可复制的函数结果通过复制消除存入std::optional?
将不可移动不可复制类型存入std::optional(由自由函数构造)
给定如下不可移动、不可复制的类型Foo,以及返回该类型的自由函数foo():
struct Foo { Foo(); Foo(Foo const&) = delete; Foo(Foo&&) = delete; Foo& operator=(Foo const&) = delete; // 为完整性添加 Foo& operator=(Foo&&) = delete; // 为完整性添加 ~Foo(); }; Foo foo();
在不修改Foo或foo()的前提下,我们可以通过复制消除直接构造对象:
Foo f1 = foo();
也能通过emplace()在std::optional内部默认构造Foo:
std::optional<Foo> f2; f2.emplace();
但无法将foo()的结果存入std::optional:
f2 = foo(); // 编译失败:需要移动/复制Foo f2.emplace(foo()); // 编译失败:Foo没有接受自身的构造函数
核心问题解答
确实没有办法实现这个需求,你并没有忽略什么。
原因在于:
std::optional要存储已构造好的Foo对象,必须通过移动或复制操作将对象转移到自身的内部存储中,但Foo的移动和复制操作都被显式删除了。- 虽然
Foo f1 = foo();能通过复制消除直接在f1的内存中构造对象,但std::optional没有提供接口让foo()直接在其内部存储中构造Foo——emplace()方法仅支持调用Foo的构造函数来初始化内部对象,无法接收一个已构造好的Foo实例(因为传递实例需要移动/复制)。
除非你能修改foo(),让它直接在指定内存地址构造Foo(比如接受一个指针参数并在该位置用placement new构造),否则在现有约束下,无法将foo()返回的对象存入std::optional。
内容的提问来源于stack exchange,提问作者bitmask
相关产品推荐
相关产品推荐

