Rokiのチラ裏

学生による学習のログ

ランダムアクセス可能な全ての範囲を無駄なくベクトル演算する

一々コンテナ毎にExpression templateを記述するのはバカバカしいので、書いてしまった。

ご覧の通り、Expression templateによって式構造を保存して遅延実行を行うため、範囲の無駄な一時オブジェクトは一切生成されない。以下のように使える。

#include<srook/range/pipe_algorithm/vector_calculator.hpp>
#include<srook/range/adaptor/copied.hpp>
#include<boost/range/algorithm_ext/iota.hpp>
#include<array>
#include<vector>

int main()
{
    using namespace srook::pipealgo::vector_calculator;

    std::array<int,4> ar1,ar2,ar3;
    std::array<int,5> result1;
    
    boost::iota(ar1,1); // ar1: 1 2 3 4
    boost::iota(ar2,*std::next(std::end(ar1),-1)); // ar2: 4 5 6 7
    boost::iota(ar3,*std::next(std::end(ar2),-1)); // ar3: 7 8 9 10

    result1 | srook::pipealgo::assign(ar1-ar2+ar3); // result1: 4 5 6 7 0
    
    std::vector<int> 
        v1 = ar1 | srook::adaptors::copied,
        v2 = ar2 | srook::adaptors::copied,
        v3 = ar3 | srook::adaptors::copied,
        result2;

    result2 | srook::pipealgo::assign(ar1+ar2+ar3,std::back_inserter(result2)); // result2: 12 15 18 21

    std::vector<int> result3 = result2 | srook::pipealgo::assign(ar1+ar2+ar3); // result3: 12 15 18 21
}

全ての範囲で利用できるようにするため、こちらが定義した演算子をADLで探索させるためにsrook::pipealgo::vector_calculatorをusing namespaceする必要がある。グローバル名前空間を汚さないように大量の要件が定義されている他、当名前空間をusing namespaceして公開される機能は演算子のみなので、然程影響がないと思われる。

  • result1の結果で示している通り、出力側の範囲の要素が入力側の範囲の要素よりも多かった場合、0で埋める。
  • result2で示している通り、出力側の任意のイテレータを指定する事が可能である。
  • result3で示している通り、返却値は出力側の範囲の参照であるため、その返却値を利用したコピーコンストラクトが可能である。