読者です 読者をやめる 読者になる 読者になる

可変個数のコンテナに適用できる zipWith のようなもの

C++

std::transform では1つのコンテナに対して所謂 map の操作を行えたり,2つのコンテナに対して所謂 zipWith を行えます.

今回は C++11 で新たに導入された Variadic Templates を使って,対象となるコンテナの数を任意個になるように拡張してみました.

template< class Func, class OutputIter, class InputIter, class... InputIters >
OutputIter zip_with( InputIter first1,
                                  InputIter last1,
                                  OutputIter d_first,
                                  Func const& func,
                                  InputIters... rest_iters )
{
    for( auto from=first1; from!=last1; ++from ){
        *d_first++ = func( *from, (*rest_iters++)... );
    }
    return d_first;
}

引数の順序が std::transform と違いますが,これは可変長引数の制約があるためです.
パラメータパックを ... で展開した時に,ついでに後置++を適用することで,すべてのイテレータを1つずつ前に進めます.

こんな感じで使えます.

int main()
{
    std::vector<int> vec1 = {1,    2,    3,    4};
    std::vector<int> vec2 = {10,   20,   30,   40};
    std::vector<int> vec3 = {100,  200,  300,  400};
    std::vector<int> vec4 = {1000, 2000, 3000, 4000};
    std::vector<int> result(4);

    zip_with( std::begin(vec1), std::end(vec1),
                      std::begin(result),
                      [](int a, int b, int c, int d){ return a+b+c+d; },
                      std::begin(vec2),
                      std::begin(vec3),
                      std::begin(vec4) );
    // result == {1111, 2222, 3333, 4444}

    return 0;
}

vec1 から vec4 までのコンテナの各要素をすべて足し合わせています.