C++11 で Boost.MPL.lambda みたいなの書いてみた

書いたことがなかったので書いてみた。

[コード]

#include <utility>
#include <tuple>


template<std::size_t Index>
struct placeholder{
    template<typename... Args>
    struct apply : std::tuple_element<Index, std::tuple<Args...>>{};

    template<typename... Args>
    using apply_t = typename apply<Args...>::type;
};

using _1 = placeholder<0>;
using _2 = placeholder<1>;

static_assert(std::is_same<_1::apply<int, double>::type, int>{}, "");
static_assert(std::is_same<_2::apply<int, double>::type, double>{}, "");


template<typename Expr, typename... Args>
struct invoke{
    template<typename Expr_, typename... Args_>
    static
    typename Expr_::template apply<Args_...>::type
    helper(bool);

    template<typename Expr_, typename... Args_>
    static
    Expr_
    helper(int);

    using type = decltype(helper<Expr, Args...>(true));
};

template<typename Expr, typename... Args>
using invoke_t = typename invoke<Expr, Args...>::type;


template<typename... Args>
struct lambda;

template<
    template<class...> class Expr,
    typename... Placeholders
>
struct lambda<Expr<Placeholders...>>{
    template<typename... Args>
    struct apply
        : std::common_type<Expr<typename ::invoke<Placeholders, Args...>::type...>>{};

    template<typename... Args>
    using apply_t = typename apply<Args...>::type;
};

using is_int = lambda<std::is_same<int, _1>>;
static_assert(is_int::apply_t<int>{}, "");
static_assert(!is_int::apply_t<float>{}, "");

static_assert(std::is_same<
    lambda<std::tuple<_2, _1>>::apply_t<int, float>,
    std::tuple<float, int>
>{}, "");


int
main(){

    return 0;
}

使ってるのは Variadic Templates と Template Aliases ぐらいですかねえ。
逆に使い勝手自体は C++03 とあんまり変わらないのでうーむ・・・