簡體   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