Srook range adaptor and Srook range pipe algorithm
※ 2018/3/11 ライブラリ整理より当エントリ内で紹介されている一部機能は削除した。
Srook Range AdaptorとSrook Range Pipe AlgorithmはSTLアルゴリズムとその他諸々の機能をイテレータアダプタによる効率的なアクセスと、パイプライン記法をサポートさせたC++14自作ラッパーライブラリである。Srook Range Adaptorは基本的に、boost range adaptorsと互換性があるが、boostには搭載されていないアダプタもある。例えば:
std::vector<int> v{2,2,2,2,2,2,3,3,3,4,5,6,7,8}; std::vector<int> result = v | boost::adaptors::replaced(2,4) | srook::adaptors::remove_copied(3); // 2を4に置換し3を排除したものをコピーする result | srook::pipealgo::print(); // 4 4 4 4 4 4 4 5 6 7 8
auto v = boost::irange(0x41,0x47) | srook::adaptors::to_range<std::vector>(); // boost::irangeと併用可能 auto li = v | srook::adaptors::to_range<std::list>(); // リストへ auto t1 = v | srook::adaptors::to_range<std::tuple,6>(); // タプルへ auto str = v | srook::adaptors::to_range<std::basic_string>(); // std::stringへ auto ar = v | srook::adaptors::to_array<std::array,6>(); // std::arrayへ auto str1 = v | srook::adaptors::to_string<std::wstring>(); // std::wstringへ auto str2 = v | srook::adaptors::to_string<std::u16string>(); // std::u16stringへ auto str3 = v | srook::adaptors::to_string<std::u32string>(); // std::u32stringへ
またSrook Range Pipe AlgorithmはSTLアルゴリズムを全てパイプライン記法で記述できるようにしたもの。よってイテレータアダプタの同機能とは、処理内容が異なる。例えば:
std::vector<int> v = boost::irange(0,9) | srook::adaptors::copied; v | srook::adaptors::reversed | srook::adaptors::print(); // 8 7 6 5 4 3 2 1 0 v | boost::adaptors::reversed | srook::adaptors::print(); // 8 7 6 5 4 3 2 1 0
v | srook::pipealgo::reverse | srook::adaptors::print(); // 8 7 6 5 4 3 2 1 0
srook::adaptors::reversed
とboost::adaptors::reversed
の動作は同じ。具体的に述べれば、イテレータによって逆順にアクセスしていくため、範囲そのもの(上記の場合v
)の内部要素らがreverseされるわけではない。しかし、srook::pipealgo::reverse
はイテレータによる逆順アクセスではなく、std::reverseを範囲に適用した形となる。std::reverse
アルゴリズムの戻り値は原則void
であるが、便宜的に渡された範囲の参照を返すようにしている。
また、メンバとして同名の関数を持っていた場合はその関数を呼び出すようにしている。例えば:
#include<srook/range/adaptor/find.hpp> std::string str("That is so good C++"); std::size_t pos = str | srook::pipealgo::find("good"s); // like that: str.find("good") std::size_t pos1 = str | srook::pipealgo::find("C++"s,pos); // like that: str.find("C++",pos) std::size_t pos2 = str | srook::pipealgo::find("C++"s,pos,"C++"s.size()); // like that: str.find("C++",pos,"C++"s.size()) std::vector<int> v{1,2,3,4,5,6,7,8}; decltype(v)::const_iterator it = v | srook::pipealgo::find(6); // like that: std::find(v.cbegin(),v.cend(),6)
#include<srook/range/adaptor/find_first_of.hpp> using namespace std::string_literals; std::vector<int> v(10); std::vector<int> hs(3); std::string str="hoge foo"; std::string search="hoge"; boost::range::iota(v,0); boost::range::iota(hs,4); const auto f=[](decltype(v)::value_type x,decltype(v)::value_type y){return x<y;}; decltype(v)::const_iterator it1 = v | srook::pipealgo::find_first_of(hs); decltype(v)::const_iterator it2 = v | srook::pipealgo::find_first_of(hs.cbegin(),hs.cend()); decltype(v)::const_iterator it3 = v | srook::pipealgo::find_first_of(hs,f); decltype(v)::const_iterator it4 = v | srook::pipealgo::find_first_of(hs.cbegin(),hs.cend(),f); std::string::size_type result1 = str | srook::pipealgo::find_first_of(search); std::string::size_type result2 = str | srook::pipealgo::find_first_of(search.c_str(),4); std::string::size_type result3 = str | srook::pipealgo::find_first_of(search.c_str(),4,search.size());
全てのコードは以下のテストコードによりテストされており、幾つかのci環境でテストコードを走らせている。サポート環境は
- boost lib version 1.63.0 or above later
- GCC 6.2.0 or above later
- Clang 3.7.0 or above later
であるが、OSはLinux環境が最も好ましい。 大体の使い方も、以下のテストコードで示されている。