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::vector
にfiltered
とtransformed
を適用した結果の型は、std::vector
やstd::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()
から返されるのは「あらゆるコンテナに変換可能な型」であるか、「コンテナがあらゆるコンテナから変換可能」である必要があります。