Template Aliases でハマった
Template Aliases でハマったので覚え書き。
まーしょっぱいエラーですね。
次のコードはエラーになります。
[ソース]
#include <boost/mpl/has_xxx.hpp> #include <boost/mpl/identity.hpp> #include <boost/mpl/if.hpp> namespace mpl = boost::mpl; BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type); template<typename T> using T_value_type = mpl::identity<typename T::value_type>; BOOST_MPL_HAS_XXX_TRAIT_DEF(type) template<typename T> using T_type = mpl::identity<typename T::type>; template<typename T> using select = typename mpl::if_< has_value_type<T>, T_value_type<T>, typename mpl::if_< has_type<T>, T_type<T>, mpl::identity<T> >::type >::type; struct vec{ typedef int value_type; }; // 以下 ::type や ::value_type が参照できなくてエラー using type1 = select<mpl::identity<float> >::type; using type2 = select<int>::type; using type3 = select<vec>::type;
つまりはこういう事らしい。
[ソース]
template<typename T> struct TT_type : T::type{}; template<typename T> using T_type = typename T::type; struct foo{}; typedef TT_type<foo> hoge; // ok typedef T_type<foo> hoge2; // error TT_type<foo> h; // error
まぁ厳密に仕様を読み込んでいるわけではないので、よく分かっていませんが……。
上記のソースだと簡略化しているので、すぐにエラー原因が分かるんですけど、元のソースでかなりアレな使い方をしていたので原因が分かるまで結構苦労しました……。
解決策としては、以下の様に struct を使用すれば動くようになります
#include <boost/mpl/has_xxx.hpp> #include <boost/mpl/identity.hpp> #include <boost/mpl/if.hpp> namespace mpl = boost::mpl; BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type); // struct を使う template<typename T> struct T_value_type : mpl::identity<typename T::value_type>{}; BOOST_MPL_HAS_XXX_TRAIT_DEF(type) template<typename T> struct T_type : mpl::identity<typename T::type>{}; template<typename T> using select = typename mpl::if_< has_value_type<T>, T_value_type<T>, typename mpl::if_< has_type<T>, T_type<T>, mpl::identity<T> >::type >::type; struct vec{ typedef int value_type; }; BOOST_MPL_ASSERT(( boost::is_same< select<mpl::identity<float> >::type, float > )); BOOST_MPL_ASSERT(( boost::is_same< select<int>::type, int > )); BOOST_MPL_ASSERT(( boost::is_same< select<vec>::type, vec::value_type > ));
[ソース]
#include <boost/mpl/if.hpp> #include <boost/mpl/equal_to.hpp> #include <boost/mpl/less_equal.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/multiplies.hpp> #include <boost/mpl/minus.hpp> #include <boost/mpl/apply.hpp> namespace mpl = boost::mpl; template<typename T> struct T_type : T::type{}; template<typename T, typename F> using fact_impl = mpl::if_< mpl::equal_to<T, mpl::int_<1> >, T, mpl::multiplies<T, T_type<mpl::apply2<F, mpl::minus<T, mpl::int_<1> >, F> > > >; template<typename T> using fact = typename fact_impl<T, fact_impl<mpl::_1, mpl::_2> >::type; BOOST_MPL_ASSERT(( mpl::equal_to< fact<mpl::int_<3> >::type, mpl::int_<6> > ));
お姉妹