2017-11-25 10 views
3

なぜマップのブレースの初期化をunique_ptrと併用できないのですか?C++マップブレースの初期化とユニークなptr

編集:g ++ 7.2をC++ 17モードで使用します。

make_pairと[]演算子を使用して、順序付けされていないマップに作成して挿入できます。

std::unordered_map<std::string, std::unique_ptr<A>> map; 

map.insert(std::make_pair("hello",std::make_unique<A>())); 
map["foo"] = std::make_unique<A>(); 

しかし、中括弧を使用すると失敗する理由はわかりません。 C++ 11は

map.insert({"foo", std::make_unique<A>()}); // Error 

error: use of deleted function ‘std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&)

+1

を持っているあなたは、C++ 14を使用しています。 – Rakete1111

+1

afaik挿入コピー(unique_ptrはコピー不可)、emplace – Sopel

答えて

1

、連想コンテナ挿入はコピーcostructible左辺値またはムーブ挿入可変右辺値のいずれかを必要とします。だから、make_pair()と一緒にinsert()を呼び出すことに問題はありません。後者はの値を初期化するために使用されるpair<const char[],unique_ptr>を構成します。

ブレースの初期化に関する問題は(何の適切VALUE_TYPE & &過負荷がないため)VALUE_TYPEのCONST &過負荷が好ましいます(17 C++まで)、従ってコピーが要求され、エラーが発生したということです。

実際、両方の形式がgcc trunkとclang 5(libC++)をC++ 17モードでコンパイルすることに注意してください。より正確には


、上のC++ 11から、関連する挿入セマンティック要件は

[unord.req] If t is a non-const rvalue expression, value_type shall be MoveInsertable into X; otherwise, value_type shall be CopyInsertable into X.

を読んで、物事が異なる実際のメンバー仕様です。 C++ 17になるまで、私たちは持っている:

pair<iterator, bool> insert(const value_type& obj); 
template <class P> pair<iterator, bool> insert(P&& obj); 
... 

一般的な過負荷がSFINAEがstd::is_constructible<value_type, P&&>::valueに拘束されています。明らかに、braced-init-listを使用すると、const &オーバーロードがここで選択されます(注意:initializer_listのオーバーロードもありますが、OPケースには適用されません)。

何の `のstd :: make_unique`がなかった前ので代わりに、C++ 17には、我々はまた、

pair<iterator, bool> insert(value_type&& obj); 
+0

はgccサポートのように見えます。C++ 17はまだ実験的です(https://gcc.gnu.org/projects/cxx-status.html)。そのため、私のためにコンパイルする(gcc 7.2)。素晴らしい説明。ありがとう。 –

関連する問題