繁体   English   中英

为什么`std :: pair`允许使用用户定义的删除move构造函数从类类型的右值进行初始化?

[英]Why does `std::pair` allow to initialize from an rvalue of class type with a user-defined deleted move constructor?

考虑以下类别:

struct Do_not_move {
    Do_not_move() = default;
    Do_not_move(const Do_not_move&) = default;
    Do_not_move(Do_not_move&&) = delete;
private:
    int dummy;
};

这里我了解到std::pair (以及std::tuple )允许从Do_not_move rvalue进行初始化,例如

Do_not_move dnm;
std::pair<int, Do_not_move> p(0, std::move(dnm)); // work well

但是,许多其他STL类拒绝这种使用。 例如,

Do_not_move dnm;
std::vector<Do_not_move> v{std::move(dnm)}; // error
std::set<Do_not_move> s{std::move(dnm)};    // error
std::any a{std::move(dnm)};                 // error

我确实知道为什么会发生这些行为。 我的问题是,为什么std::pair设计得如此特别?

我知道为什么会发生这些行为...

不,在您的示例中,您正在调用std::vector::vector(std::initializer_list)std::set::set(std::initializer_list) 不幸的是std::initializer_list<T>基本上是const T[]数组上的糖-这意味着您不能从initializer_list移出。

std::any a{std::move(dnm)}; 在wandbox.org上编译精细示例


为什么std::pair设计得如此特别?

不是。 碰巧同时具有这两个构造函数:

constexpr pair( const T1& x, const T2& y ); // (0)

template <typename U1, typename U2>
constexpr pair( U1&& x, U2&& y );  // (1)

根据cppreference ,这些构造函数对SFINAE友好(即,如果构造无效,它们将不参与重载解析)

调用时

std::pair<int, Do_not_move> p(0, std::move(dnm));

首先,我们尝试使用(1) ,这是无效的。 它被SFINAE淘汰,所以(0)仍然存在。 这很好,因为T&&绑定到const T& ,并执行复制。

如果我不得不猜测 为什么 std::pair具有这两个构造函数:在创建转发引用之前,该类可用,并且仅暴露(0) 将转发引用引入该语言时, (1)被添加到std::pair 可能为了保持向后兼容性,构造函数被设计为对SFINAE友好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM