Boost Range LibraryのRangeアダプタは、リスト処理を遅延評価する仕組みを提供する。
インデックス
- 条件抽出 -
filtered
- 値の変換 -
transformed
- 型変換 -
transformed
- 逆順に走査する -
reversed
- mapのキーのみを抽出する -
map_keys
- mapの値のみを抽出する -
map_values
- 2つのリストを連結する -
join
- 値の範囲を生成する -
irange
- リストに対する複数の遅延処理を合成する
条件抽出 - filtered
リストから値の条件抽出をするには、boost::adaptors::filtered
を使用する。
以下は、{1, 2, 3, 4, 5}
というリストから、偶数値のみを抽出している。
#include <iostream>
#include <vector>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/for_each.hpp>
using namespace boost::adaptors;
bool is_even(int x) { return x % 2 == 0; }
void disp(int x) { std::cout << x << std::endl; }
int main()
{
const std::vector<int> v = boost::assign::list_of(1)(2)(3)(4)(5);
boost::for_each(v | filtered(is_even), disp);
}
実行結果:
2
4
値の変換 - transformed
リストの全ての要素に関数を適用するには、boost::adaptors::transformed
を使用する。
これは、関数型言語一般でのmap
関数に相当する。
以下は、リストの全ての要素に1
を加算する処理である。
#include <iostream>
#include <vector>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/for_each.hpp>
using namespace boost::adaptors;
int add(int x) { return x + 1; }
void disp(int x) { std::cout << x << std::endl; }
int main()
{
const std::vector<int> v = boost::assign::list_of(1)(2)(3)(4)(5);
boost::for_each(v | transformed(add), disp);
}
実行結果:
2
3
4
5
6
型変換 - transformed
リストの全ての要素に関数を適用するboost::adaptors::transformed
は、型変換にも使用することができる。
以下は、リストの全ての要素をint
からstd::string
に変換する処理である。
#include <iostream>
#include <vector>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/lexical_cast.hpp>
using namespace boost::adaptors;
std::string int_to_string(int x) { return boost::lexical_cast<std::string>(x); }
void disp(const std::string& s) { std::cout << s << std::endl; }
int main()
{
const std::vector<int> v = boost::assign::list_of(1)(2)(3)(4)(5);
boost::for_each(v | transformed(int_to_string), disp);
}
実行結果:
1
2
3
4
5
逆順に走査する - reversed
リストを逆順に走査するには、boost::adaptors::reversed
を使用する。
#include <iostream>
#include <vector>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/algorithm/for_each.hpp>
using namespace boost::adaptors;
void disp(int x) { std::cout << x << std::endl; }
int main()
{
const std::vector<int> v = boost::assign::list_of(1)(2)(3)(4)(5);
boost::for_each(v | reversed, disp);
}
実行結果:
5
4
3
2
1
mapのキーのみを抽出する - map_keys
std::map
、boost::unordered_map
、std::vector<std::pair<Key, Value> >
のようなコンテナからキーのみを抽出するには、boost::adaptors::map_keys
を使用する。
#include <iostream>
#include <map>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/for_each.hpp>
using namespace boost::adaptors;
void disp(int x) { std::cout << x << std::endl; }
int main()
{
const std::map<int, std::string> m = boost::assign::map_list_of
(3, "Alice")
(1, "Bob")
(4, "Carol")
;
boost::for_each(m | map_keys, disp);
}
実行結果:
1
3
4
mapの値のみを抽出する - map_values
std::map
、boost::unordered_map
、std::vector<std::pair<Key, Value> >
のようなコンテナから値のみを抽出するには、boost::adaptors::map_values
を使用する。
#include <iostream>
#include <map>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/for_each.hpp>
using namespace boost::adaptors;
void disp(const std::string& s) { std::cout << s << std::endl; }
int main()
{
const std::map<int, std::string> m = boost::assign::map_list_of
(3, "Alice")
(1, "Bob")
(4, "Carol")
;
boost::for_each(m | map_values, disp);
}
実行結果:
Bob
Alice
Carol
2つのリストを連結する - join
リストを連結するには、boost::join()
関数を使用する。
この関数は、2つのリストを連結した新たなリストを返すのではなく、1つのリストの走査が終わったら2つめのリストを走査するRangeを返す。
#include <iostream>
#include <vector>
#include <list>
#include <boost/assign/list_of.hpp>
#include <boost/range/join.hpp>
#include <boost/range/algorithm/for_each.hpp>
void disp(int x) { std::cout << x << std::endl; }
int main()
{
const std::vector<int> v = boost::assign::list_of(1)(2)(3);
const std::list<int> ls = boost::assign::list_of(4)(5);
boost::for_each(boost::join(v, ls), disp);
}
実行結果:
1
2
3
4
5
値の範囲を生成する - irange
{1..5}
のような連続した値の範囲を生成する場合には、boost::irange()
関数を使用する。
この関数に値の範囲を引数として渡すことで、その値の範囲を走査可能なRandom Access Rangeを返す。
#include <iostream>
#include <boost/range/irange.hpp>
#include <boost/range/algorithm/for_each.hpp>
void disp(int x) { std::cout << x << std::endl; }
int main()
{
// [1, 5)の範囲を生成する
boost::for_each(boost::irange(1, 5), disp);
}
実行結果:
1
2
3
4
また、irange
には、第3引数として、値を進めるステップ値も指定することができる。
これを指定することで、「値を2ずつ進める」といったことが可能になる。
#include <iostream>
#include <boost/range/irange.hpp>
#include <boost/range/algorithm/for_each.hpp>
void disp(int x) { std::cout << x << std::endl; }
int main()
{
// [1, 10)の範囲を、2ずつ進める
boost::for_each(boost::irange(1, 10, 2), disp);
}
実行結果:
1
3
5
7
リストに対する複数の遅延処理を合成する
Boost Range LibraryのRangeアダプタは、個々の処理を遅延評価するだけでなく、operator|()
でさらに繋ぎ、それらの処理を合成できる。
以下は、条件抽出(filtered
)と関数適用(transformed
)を合成する処理である。リストが実際に走査されそれらの処理が必要になるまで評価が遅延される。
#include <iostream>
#include <vector>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/for_each.hpp>
using namespace boost::adaptors;
bool is_even(int x) { return x % 2 == 0; }
int add(int x) { return x + 1; }
void disp(int x) { std::cout << x << std::endl; }
int main()
{
const std::vector<int> v = boost::assign::list_of(1)(2)(3)(4)(5);
boost::for_each(v | filtered(is_even) | transformed(add), disp);
}
実行結果:
3
5