为什么当T不可移动时,STD ::可选的移动构建体不会被删除

Why is the move-constructor of std::optional not deleted when T is not move-constructible?

本文关键字:构建 移动 删除 可移动 为什么 STD      更新时间:2023-10-16

根据标准, std::optional<T>的复制构造人:

...除非 is_copy_constructible_v<T>true

,应将其定义为删除

但是std::optional<T>的移动结构器:

...除非is_move_constructible_v<T>true

,不得参与过载分辨率

我了解已删除的构造函数,不删除std::optional<T>的移动构造符的目的是允许这样的代码:

std::optional<X> o1;
std::optional<X> o2(std::move(o1));

...要依靠某些转换序列工作-o2将由使用std::optional<X>&&构建的类型A对象构造(如果我错了,请纠正我)。

但是,关于std::optional的可能构造函数,我很难弄清楚可以匹配此用例的构造函数...

为什么std::optional<T>的移动构建器根本不是如果T不可移动?

明确删除它意味着它将是最好的匹配X值,从而导致编译时间错误,而不是采用这些案件的复制构造人。

ex:

#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

明确删除的功能仍然参与超负荷分辨率,可以是最好的匹配。这很有用,例如,禁用某些转换。

委员会真的不在乎可复制但不可移动的憎恶。参见,例如,对LWG问题2768的讨论,该问题的特征是"病理"和以前将其支持为"疯狂"的尝试。

除非有某些特殊原因陷入呼叫(例如,例如,LWG问题2766-但可能会导致不良副作用,否则这种内容的默认措辞通常是"不得参与过载分辨率",除非有某些特殊原因(例如,有时是适当的)例如LWG问题2993)。对于复制特殊成员,根本无法在概念之前完成,因此必须使用"定义为已删除"。对于移动特殊成员,"定义为已删除"的OTOH是不够精确的,因为"明确删除的移动"answers"被隐式定义为已删除的删除"之间存在巨大差异:后者不参与过载分辨率。

另请参见《 LWG问题》第2958页的讨论。