「階層化された型リスト」で、連続したメタ関数の適用が書きやすくなったので
Maybeモナドもいけるかな、と思って作ってみました。
#include <iostream> #include <boost/type_traits.hpp> #include <boost/mpl/if.hpp> template <class T> struct just; struct nothing; template <class T> struct return_ { typedef just<T> type; }; template <class T> struct return_<just<T> > { typedef just<T> type; }; template <class T> class maybe { template <class Maybe> struct is_integral_; template <class T> struct is_integral_<just<T> > { typedef typename boost::mpl::if_< boost::is_integral<T>, maybe<just<T> >, maybe<nothing> >::type type; }; template <> struct is_integral_<nothing> { typedef maybe<nothing> type; }; template <class> struct fail_ { typedef maybe<nothing> type; }; template <class Maybe> struct success_; template <class T> struct success_<just<T> > { typedef maybe<just<T> > type; }; template <> struct success_<nothing> { typedef maybe<nothing> type; }; public: typedef typename is_integral_<T>::type is_integral; typedef typename fail_<T>::type fail; typedef typename success_<T>::type success; typedef typename T result; }; template <class Maybe> struct print; template <class T> struct print<just<T> > { void operator()() const { std::cout << typeid(T).name() << std::endl; } }; template <> struct print<nothing> { void operator()() const { std::cout << "nothing" << std::endl; } }; int main() { print<maybe<return_<int>::type>::is_integral::result>()(); // int print<maybe<return_<int>::type>::is_integral::fail::result>()(); // nothing print<maybe<return_<int>::type>::is_integral::fail::success::result>()(); // nothing print<maybe<return_<void>::type>::is_integral::result>()(); // nothing print<maybe<return_<void>::type>::is_integral::success::result>()(); // nothing }
連続したメタ関数適用のうち、途中でnothingが返ったらその後のメタ関数適用は全てnothingが返り、
全て成功したときのみjust
return_は型Tをjust
is_integralは整数型だったらjust
failは問答無用でnothing(失敗)を返します。
successはjust
【追記:2009/12/05 22:43】
GCC 4.xで動かないという報告をいただいたので修正しました。
#include <iostream> #include <typeinfo> #include <boost/type_traits.hpp> #include <boost/mpl/if.hpp> template <class T> struct just; struct nothing; template <class T> struct return_ { typedef just<T> type; }; template <class T> struct return_<just<T> > { typedef just<T> type; }; template <class T> class maybe { template <class Maybe> struct is_integral_ { typedef maybe<nothing> type; }; template <class T1> struct is_integral_<just<T1> > { typedef typename boost::mpl::if_< boost::is_integral<T1>, maybe<just<T1> >, maybe<nothing> >::type type; }; template <class> struct fail_ { typedef maybe<nothing> type; }; template <class Maybe> struct success_ { typedef maybe<nothing> type; }; template <class T1> struct success_<just<T1> > { typedef maybe<just<T1> > type; }; public: typedef typename is_integral_<T>::type is_integral; typedef typename fail_<T>::type fail; typedef typename success_<T>::type success; typedef T result; }; template <class Maybe> struct print; template <class T> struct print<just<T> > { void operator()() const { std::cout << typeid(T).name() << std::endl; } }; template <> struct print<nothing> { void operator()() const { std::cout << "nothing" << std::endl; } }; int main() { print<maybe<return_<int>::type>::is_integral::result>()(); // int print<maybe<return_<int>::type>::is_integral::fail::result>()(); // nothing print<maybe<return_<int>::type>::is_integral::fail::success::result>()(); // nothing print<maybe<return_<void>::type>::is_integral::result>()(); // nothing print<maybe<return_<void>::type>::is_integral::success::result>()(); // nothing }