template class を受け取る is_same メタ関数

※長いです。

#include <boost/mpl/bool.hpp>
#include <boost/mpl/assert.hpp>

namespace mpl = boost::mpl;

struct _{};

template<typename T>
struct quote{};

template<
    template <typename> class T
>
struct quote1 : T<_>{
    typedef T<_> type;
};

template<
    template <typename, typename> class T
>
struct quote2 : T<_, _>{
    typedef T<_, _> type;
};

template<typename T, typename U>
struct is_same_class : mpl::false_{};

template<typename T>
struct is_same_class<T, T> : mpl::true_{};

template<
    template <typename> class T
>
struct is_same_class<T<_>, T<_> > : mpl::true_{};

template<
    template <typename> class T,
    typename Arg1
>
struct is_same_class<T<_>, T<Arg1> > : mpl::true_{};

template<
    template <typename> class T,
    typename Arg1
>
struct is_same_class<T<Arg1>, T<_> > : mpl::true_{};


template<
    template <typename, typename> class T
>
struct is_same_class<T<_, _>, T<_, _> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg
>
struct is_same_class<T<Arg, _>, T<_, _> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg
>
struct is_same_class<T<_, Arg>, T<_, _> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg
>
struct is_same_class<T<_, _>, T<Arg, _> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg
>
struct is_same_class<T<_, _>, T<_, Arg> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg1, typename Arg2
>
struct is_same_class<T<_, Arg2>, T<Arg1, Arg2> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg1, typename Arg2
>
struct is_same_class<T<Arg1, _>, T<Arg1, Arg2> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg1, typename Arg2
>
struct is_same_class<T<Arg1, Arg2>, T<_, Arg2> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg1, typename Arg2
>
struct is_same_class<T<Arg1, Arg2>, T<Arg1, _> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg1, typename Arg2
>
struct is_same_class<T<_, _>, T<Arg1, Arg2> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg1, typename Arg2
>
struct is_same_class<T<Arg1, Arg2>, T<_, _> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg1, typename Arg2
>
struct is_same_class<T<Arg1, _>, T<_, Arg2> > : mpl::true_{};

template<
    template <typename, typename> class T,
    typename Arg1, typename Arg2
>
struct is_same_class<T<_, Arg2>, T<Arg1, _> > : mpl::true_{};


//----------------------------------------------------------
// 適当なテスト
template<typename T>
struct hoge{};

BOOST_MPL_ASSERT((is_same_class<hoge<int>, hoge<int> >::type));
BOOST_MPL_ASSERT((is_same_class<hoge<_>,   hoge<float> >::type));

template<typename T>
struct is_hoge : is_same_class<quote1<hoge>::type, T>{};

BOOST_MPL_ASSERT_NOT((is_hoge<float>::type));
BOOST_MPL_ASSERT    ((is_hoge<hoge<int> >::type));
BOOST_MPL_ASSERT    ((is_hoge<hoge<_> >::type));


template<typename T, typename U>
struct hoge2{};

template<typename T>
struct is_hoge2 : is_same_class<quote2<hoge2>::type, T>{};

BOOST_MPL_ASSERT    ((is_same_class<hoge2<int, _>,   hoge2<_, char> >::type));
BOOST_MPL_ASSERT_NOT((is_same_class<hoge2<int, int>, hoge2<float, char> >::type));
BOOST_MPL_ASSERT    ((is_same_class<hoge2<_, _>,     hoge2<int, float> >::type));
BOOST_MPL_ASSERT_NOT((is_same_class<hoge2<_, _>,     int>::type));
BOOST_MPL_ASSERT_NOT((is_hoge2<int>::type));
BOOST_MPL_ASSERT    ((is_hoge2<hoge2<int, float> >::type));

int
main(){
    return 0;
}


template class を渡すことが出来る is_same を書いてみました。
部分的に一致するか否かの設定も行うことが出来ます。


とりあえず、何も考えずにそのままガシガシ書いているのでかなり助長。
一応、問題なく動いているかな?
template 引数が2つだけで爆発しそうなので、3つとかに対応させると発狂しそう。
Boost.PP あたりででサックリ書きたい。