2013-02-16 2 views
10

は、次のコードを見てください:のstd ::コピー不能オブジェクトを使用してマップ<> ::挿入し、均一な初期化

#include <utility> 
#include <map> 

// non-copyable but movable 
struct non_copyable { 
    non_copyable() = default; 

    non_copyable(non_copyable&&) = default; 
    non_copyable& operator=(non_copyable&&) = default; 

    // you shall not copy 
    non_copyable(const non_copyable&) = delete; 
    non_copyable& operator=(const non_copyable&) = delete; 
}; 

int main() { 
    std::map<int, non_copyable> map; 
    //map.insert({ 1, non_copyable() }); < FAILS 
    map.insert(std::make_pair(1, non_copyable())); 
    //^same and works 
} 

がg ++ 4.7の標線をコメントアウトするとき、このスニペットが失敗したコンパイル。生成されたエラーは、non_copyableがコピーできないことを示しますが、私はそれが移動されることを期待しました。

なぜ均一な初期設定を使用して構築std::pairを挿入しない失敗ではなくstd::make_pairを使用して構築さ1?両方ともうまくマップに移動することができる値を生成するとは思われませんか?

答えて

17

[これは完全に書き直しです。 。

  • insert(const value_type& value)、および

  • <template typename P> insert(P&& value):私の以前の答えは、問題とは何の関係もありませんでした]

    mapは、2つの関連insertオーバーロードがあります。

単純リスト初期化子map.insert({1, non_copyable()});を使用すると、すべての可能なオーバーロードが考慮されます。しかし、唯一の最初の1(const value_type&を取る1)は、他のは意味がありませんので、(魔法のようにあなたがペアを作成することを意図していることを推測する方法はありません)、発見されました。最初の­の負荷は、あなたの要素がコピーできないので、もちろん機能しません。

あなたはすでに説明したようmake_pair、との、または明示的に値型に名前を付けるのいずれかによって、明示的にペアを作成することにより、第2の過負荷作業を行うことができます。

typedef std::map<int, non_copyable> map_type; 

map_type m; 
m.insert(map_type::value_type({1, non_copyable()})); 

今リスト初期化子を探すために知っていますmap_type::value_typeコンストラクタは、関連MOVA ­ BLEものを見つけ、その結果はinsert関数のP&& -overloadに結合右辺値対です。

は、私がここに道徳的な仮定

(別のオプションは。それは多くの、より詳細ななるだろうけれども、piecewise_constructforward_as_tupleemplace()を使用することです)、そのリスト-初期化子が実行可能な過負荷–を探しているが、彼らは知っている必要があります何を探して!

+1

はい、それは私が私の答えを削除する前に書いたものは基本的です。私は疑問があります:なぜ、 'initializer_list <>'はここで作られていますか? 'std :: pair 'はコンストラクタを持っていないようです。私は均一な初期化構文が 'pair <>'の通常のコンストラクタを選ぶと思っていました。 –

+1

また、initializer_list <>要素はすべて同じ型でなければなりません。両方のコメントに – eladidan

+0

+1。私の例では、「initializer_list」はありません。これは、一様初期化を使用する 'std :: pair'コンストラクタの呼び出しのようなものです。 – mfontanini

関連する問題