2013-11-25

久しぶりにメタプログラミングらしいメタプログラミングをした

zip

これをみて、早速実装を始めたが、残念ながらボレロ村上さんに抜かれてしまった。

ボレロ村上の実装

ボレロ村上さんのコードを参考にしたわけではないが、書き終わってから見ると、同じになっていた。

江添の実装

#include <iostream>
#include <array>
#include <tuple>
#include <cstddef>


template< std::size_t ... >
struct index_seq { } ;

template < std::size_t N, typename T >
struct make_index_seq_impl ;

template < std::size_t N, std::size_t ... I  >
struct make_index_seq_impl< N, index_seq< I ... > >
{
    using type = typename make_index_seq_impl< N-1, index_seq< N-1, I... > >::type ;
} ;


template < std::size_t ... I  > 
struct make_index_seq_impl< 0, index_seq< I ... > >
{
    using type = index_seq< I... > ;
} ;

template< std::size_t N >
using make_index_seq = typename make_index_seq_impl< N , index_seq< > >::type ;

template < std::size_t I, std::size_t N, typename ... Types >
constexpr auto make_unpacked_tuple( std::array< Types, N > const & ... containers )
    -> std::tuple< Types ... >
{
    return std::make_tuple( containers[I]... ) ;
}

template < std::size_t N, std::size_t ... I, typename ... Types >
constexpr auto zip_aux( index_seq< I ... >, std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return std::array< std::tuple< Types ... >, N >{ { make_unpacked_tuple<I>( containers... )... } } ;
} 

template < std::size_t N, typename ... Types >
constexpr auto zip( std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return zip_aux( make_index_seq< N >(), containers ... ) ;
}

int main()
{
    constexpr std::array<int, 5>  a = { { 1, 2, 3, 4, 5 } };
    constexpr std::array<char, 5> b = { { 'a', 'b', 'c', 'd', 'e' } };

    auto c = zip<5>(a, b) ;


    for ( auto const & i : c )
    {
        std::cout << std::get<0>(i) << " , " << std::get<1>(i) << '\n' ;
    }
}

なお、ここで使っているindex_seqは、今、標準ライブラリに提案されている。

本の虫: C++ 2013-01 mailingの簡易レビュー

ちなみに、これはコンパイル時実行にこだわっているからこうなるのであって、実行時実行なら、普通に以下のように書ける。

zip.cpp

No comments: