MPL でカリー化
curryN<F> で,N-ary なメタ関数クラス F をカリー化します.
#ifndef CURRY_HPP #define CURRY_HPP #include <boost/mpl/bind.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/protect.hpp> #include <boost/preprocessor/arithmetic/dec.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/iteration/local.hpp> #include <boost/preprocessor/repetition/enum_shifted_params.hpp> template <class F> struct curry1 : F {}; #define BOOST_PP_LOCAL_MACRO(n) \ template <class F> \ struct BOOST_PP_CAT(curry, n) \ { \ template <class A1> \ struct apply \ { \ typedef \ BOOST_PP_CAT(curry, BOOST_PP_DEC(n))< \ boost::mpl::protect< \ BOOST_PP_CAT(boost::mpl::bind, n)< \ F, \ A1, \ BOOST_PP_ENUM_SHIFTED_PARAMS(n, boost::mpl::_) \ > \ > \ > \ type; \ }; \ }; \ /**/ #define BOOST_PP_LOCAL_LIMITS (2, BOOST_MPL_LIMIT_METAFUNCTION_ARITY) #include BOOST_PP_LOCAL_ITERATE() #endif
#include <boost/mpl/assert.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/plus.hpp> #include "curry.hpp" using namespace boost::mpl; struct my_plus { template <class A1, class A2, class A3> struct apply : plus<A1, A2, A3> {}; }; typedef curry3<my_plus> curried_my_plus; BOOST_MPL_ASSERT_RELATION( curried_my_plus::apply<int_<1> >::type::apply<int_<2> >::type::apply<int_<3> >::type::value, ==, 6 );
bind や protect に合わせて,::type せずに使う仕様にしています.