inits, scan

メタプロは続くよどこまでも。

// inits
// リストのすべての先頭部分リストを長さの増加する順に並べたリストを返す
// [α]→[[α]]
namespace inits_detail
{
    template<class L1>
    struct concat_bind
    {
        template<class L2>
        struct f
        {
            typedef typename binary_concat<L1, L2>::type type;
        };
    };
}

template<class L>
struct inits;

template<>
struct inits<tuple<>>
{
    typedef tuple<tuple<>> type;
};

template<class Head, class... Tail>
struct inits<tuple<Head, Tail...>>
{
    typedef typename binary_concat<
        tuple<tuple<>>,
        typename map<inits_detail::concat_bind<tuple<Head>>::template f, typename inits<tuple<Tail...>>::type>::type
    >::type type;
};

// 30.scan
// リストのすべての前部リストに foldl を適用する
// (α→β→α)→α→[β]→[α]
namespace scan_detail
{
    template<template<class, class> class F, class A>
    struct foldl_bind
    {
        template<class L>
        struct f
        {
            typedef typename foldl<F, A, L>::type type;
        };
    };
};

template<template<class, class> class F, class A, class L>
struct scan
{
    typedef typename map<scan_detail::foldl_bind<F, A>::template f, typename inits<L>::type>::type type;
};
template<class Num1, class Num2>
struct plus;

template<int N1, int N2>
struct plus<int_<N1>, int_<N2>>
{
    typedef int_<N1 + N2> type;
};

int main()
{
    typedef inits<tuple<_1i, _3i, _2i>>::type inits_result;
    static_assert(is_same<inits_result, tuple<tuple<>, tuple<_1i>, tuple<_1i, _3i>, tuple<_1i, _3i, _2i>>>::value, "failed");

    typedef scan<plus, _0i, tuple<_1i, _2i, _3i, _4i, _5i>>::type scan_result;
    static_assert(is_same<scan_result, tuple<_0i, _1i, _3i, _6i, int_<10>, int_<15>>>::value, "failed");
}

しかしこの可読性の悪さといったらもう……。