根据标准,std::optional<T>
的复制构造函数:
除非is_copy_constructible_v<T>
为true
,否则...将被定义为已删除。
但是std::optional<T>
的移动构造函数:
...除非
is_move_constructible_v<T>
为true
,否则不得参与重载决策。
在我understand deleted constructors时,不删除std::optional<T>
的move-constructor的目的是允许这样的代码:
std::optional<X> o1;
std::optional<X> o2(std::move(o1));
...依靠某些转化顺序工作 - o2
将由A
类型的对象构建,该对象使用std::optional<X>&&
构建(如果我错了,请更正我) )。
但是关于std::optional
的可能构造函数,我很难找到一个可以匹配这个用例的...
如果std::optional<T>
不能移动构建,为什么T
的移动构造函数根本不会删除?
答案 0 :(得分:11)
明确删除它意味着它将是最佳匹配 x值,因此导致编译时错误,而不是 采取这些案件的复制构造函数。
例如:
#include <utility>
struct X
{
X() = default;
X(const X&) = default;
X(X&&) = delete;
};
int main()
{
X a;
X b(std::move(a));
}
这将导致类似:
'X::X(X &&)': attempting to reference a deleted function
显式删除的功能仍然参与重载 分辨率,可以是最佳匹配。这可能很有用, 例如,禁用某些转换。
答案 1 :(得分:4)
委员会真的不关心可复制但不可移动的可憎之事。例如,参见LWG issue 2768的讨论,其中将这种类型描述为“病态的”,以及早先将其称为“疯狂”的尝试。
这种东西的默认措辞一般是“不应参与重载决策”,除非有一些特殊的理由来捕获呼叫(有时候是合适的 - 例如LWG issue 2766 - 但是会导致不合需要的副作用,如LWG issue 2993)。对于复制特殊成员,在概念之前根本无法完成,因此必须使用“定义为已删除”。对于移动特殊成员,OTOH“定义为删除”不够精确,因为“明确删除的移动”和“隐式定义为删除的默认移动”之间存在巨大差异:后者不参与重载解析。
另见LWG issue 2958的讨论。