読者です 読者をやめる 読者になる 読者になる

C++1z 連想コンテナの接合

C++

C++1zでは、2つの連想コンテナを接合(splice)する機能が入ります。対象は、mapsetunordered_mapunordered_setとそれらのmulti版すべてです。

まず、特定の要素を抽出する機能として、extract()メンバ関数が追加されます。

node_type extract(const_iterator position);
node_type extract(const key_type& x);

要素を抽出する操作にともない、すべての連想コンテナに、node_typeという入れ子型が追加されます。その実装となる型は、標準ライブラリの機能としては定義されず、連想コンテナの要件としてnode_typeができることが定義されます。

次に、抽出した要素をほかのコンテナに挿入する機能として、insert()メンバ関数node_typeを受け取るオーバーロードが追加されます。

insert_return_type insert(node_type&& nh);
iterator insert(const_iterator hint, node_type&& nh);

この挿入機能のために、非multi連想コンテナにinsert_return_typeという入れ子型が追加されます。multi連想コンテナはiteratorを返します。insert_return_type型も標準ライブラリの機能としてではなく、要件として定義されます。この型は、以下のメンバ変数を持ちます:

bool inserted;        // 挿入が成功したか
X::iterator position; // 挿入した要素を指すイテレータ
X::node_type node;    // 指定されたノード

最後に、2つの連想コンテナをまるまる接合するmerge()メンバ関数が追加されます。このメンバ関数は、multi版と非multi版の両方のコンテナを受け取れます。たとえばmapの場合は、以下のメンバ関数を持ちます。

template <class C2>
void merge(map<Key, T, C2, Allocator>& source);

template <class C2>
void merge(map<Key, T, C2, Allocator>&& source);

template <class C2>
void merge(multimap<Key, T, C2, Allocator>& source);

template <class C2>
void merge(multimap<Key, T, C2, Allocator>&& source);

サンプルコード : 抽出と挿入

#include <map>
#include <string>

int main()
{
    std::map<int, std::string> src {{1,"one"}, {2,"two"}, {3,"buckle my shoe"}};
    std::map<int, std::string> dst {{3,"three"}};

    dst.insert(src.extract(src.find(1))); // イテレータ版
    dst.insert(src.extract(2)); // キー版

    // 挿入先にすでに同一キーの要素がある場合は、挿入されない
    auto r = dst.insert(src.extract(3));

//  src == {}
//  dst == {"one", "two", "three"}
//  r.position == dst.begin() + 2
//  r.inserted == false
//  r.node == "buckle my shoe"
}

サンプルコード : コンテナまるごとマージ

#include <set>

int main()
{
    std::set<int> src{1, 3, 5};
    std::set<int> dst{2, 4, 5};

    dst.merge(src); // srcをdstにマージ

    // マージできなかった要素はsrcに残る
//  src == {5}
//  dst == {1, 2, 3, 4, 5}
}

参照

お断り

この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。