Rokiのチラ裏

学生による学習のログ

Srook range adaptor and Srook range pipe algorithm

※ 2018/3/11 ライブラリ整理より当エントリ内で紹介されている一部機能は削除した。
Srook Range AdaptorとSrook Range Pipe AlgorithmSTLアルゴリズムとその他諸々の機能をイテレータアダプタによる効率的なアクセスと、パイプライン記法をサポートさせた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::reversedboost::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環境が最も好ましい。 大体の使い方も、以下のテストコードで示されている。