Sprout.Tuple で transform_view

Sprout 側で処理できるようにゴニョゴニョと拡張してみました。

[ソース]

#define SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION
#include <functional>
#include <sprout/tuple.hpp>
#include <sprout/string.hpp>


template<typename Tuple, typename F>
struct transform_view_tuple{
    Tuple tuple;
    F func;
};


namespace sprout{
    namespace tuples{

        template<std::size_t I, typename Tuple, typename F>
        struct tuple_element<I, transform_view_tuple<Tuple, F>>
            : std::result_of<F(typename tuple_element<I, Tuple>::type)>
        {};

        template<typename Tuple, typename F>
        struct tuple_size<transform_view_tuple<Tuple, F>>
            : tuple_size<Tuple>{};

        template<typename Tuple, typename F>
        struct tuple_size<transform_view_tuple<Tuple, F> const>
            : tuple_size<Tuple>{};

        template<typename Tuple, typename F>
        struct rebind_types<transform_view_tuple<Tuple, F>>
            : rebind_types<Tuple>
        {};

        template<std::size_t I, typename Tuple, typename F>
        SPROUT_CONSTEXPR auto
        get(transform_view_tuple<Tuple, F> const& tuple) SPROUT_NOEXCEPT
        ->decltype(tuple.func(sprout::get<I>(tuple.tuple)))
        {
            return tuple.func(sprout::get<I>(tuple.tuple));
        }
    }  // namespace tuples
}  // namespace sprout


template<typename Tuple, typename F>
SPROUT_CONSTEXPR transform_view_tuple<Tuple, F>
transform_view(Tuple const& tuple, F func){
    return { tuple, func };
}


#include <iostream>
#include <sprout/tuple/algorithm/copy.hpp>


struct twice{
    template<typename T>
    constexpr auto
    operator ()(T&& t)
    ->decltype(t + t){
        return t + t;
    }
};

int
main(){
    constexpr auto t = sprout::make_tuple(1, 1.25f, sprout::to_string("homu"));
    
    constexpr auto result = transform_view(t, twice());
    constexpr auto result_check(sprout::make_tuple(2, 2.5f, sprout::to_string("homuhomu")));
    static_assert(
        sprout::tuples::copy(decltype(result_check){}, result) == result_check,
    "");

    return 0;
}

やっていることは要素のアクセス時に変換関数を噛ませているだけですね。
operator はそのままだと使用できないので、Sprout.Tuple に変換してから比較しています。
constexpr Boost.Fusion が欲しくなる。

[コンパイラ]

  • g++ (GCC) 4.7.0 20111112 (experimental)