template クラスの SFINAE

template<
    typename T,
    typename U = void
>
struct has_value_type{
    static const bool value = false;
};

template<typename T>
struct has_value_type<T, typename T::value_type>{
    static const bool value = true;
};

最初はこんな感じでやろうとしたんですが、これだとうまく行きませんでした。

template<typename T>
struct sfinae_helper{
    typedef void type;
};

template<
    typename T,
    typename U = void
>
struct has_value_type{
    static const bool value = false;
};

template<typename T>
struct has_value_type<T, typename sfinae_helper<typename T::value_type>::type>{
    static const bool value = true;
};


struct hoge{
    typedef int value_type;
};
struct foo{};

BOOST_STATIC_ASSERT(( has_value_type<hoge>::value ));    // ok
BOOST_STATIC_ASSERT(( has_value_type<foo>::value ));    // error

sfinae_helper を噛ませればうまくいきました。
今まで何も考えずに sfinae_helper を用意していたんですがちゃんと意味があったんですね…。
やっぱり、理解して使わないとダメですねー。


[おまけ]

template<typename T, typename U = void>
struct value_type;

template<typename T>
struct value_type<T, typename boost::enable_if<has_value_type<T> >::type >{
    typedef typename T::value_type type;
};

value_type<hoge>::type;    // ok
value_type<foo>::type;    // error

enable_if を使って切り替えはこんな感じになります。