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

C++1y コンテナに、Rangeを受け取るコンストラクタを追加する提案

C++

N3513 Range arguments for container constructors and methods, wording revision 2


C++11現在、コンテナには「何らかのイテレータの範囲から初期化するコンストラクタ」と「初期化子リストから初期化するコンストラクタ」がありますが、これに「なんらかのRangeから初期化するコンストラクタ」を追加しよう、という提案。


いくつかの状況で、これが必要になります。
まず、Boost.RangeにあるRangeアダプタを適用した結果を、特定のコンテナに持ちたい場合。

bool is_even(int x) { return x % 2 == 0; }
int add(int x) { return x + 1; }

std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<int> v2 { v1 | filtered(is_even) | transformed(add) };

std::vectorfilteredtransformedを適用した結果の型は、std::vectorstd::dequeのようなコンテナ型ではなく、transform_range<filter_range<vector<int>, Pred>, F>のような重ね掛けされたRange型になっています。このような場合には、私のOvenToBoostにあるようなas_containerを使ったり、あるいはcopy()アルゴリズムを使ったりする必要があるのですが、Rangeを受け取るコンストラクタがコンテナ内部に用意されていれば、そういったものを使うことなく、あらゆるRangeを他のコンテナに変換できるようになります。


他の状況としては、文字列を分割するsplit()関数のようなケース。

vector<string> v{std::split("a,b,c", ",")};
deque<string>  d{std::split("a,b,c", ",")};
set<string>    s{std::split("a,b,c", ",")};
list<string>   l{std::split("a,b,c", ",")};

split()の戻り値となるコンテナをstd::vectorとかに決め打ちにしてしまうと、他のコンテナの場合には、なんらかの変換を使わないといけなくて不便です。なので、split()から返されるのは「あらゆるコンテナに変換可能な型」であるか、「コンテナがあらゆるコンテナから変換可能」である必要があります。