#ifndef BINDER_CURRIED_HPP_INCLUDED #define BINDER_CURRIED_HPP_INCLUDED #include template < typename BinderPrev //typename BinderPrev // = binder_curried_inherit_next // | binder_curried_inherit_base //IOW, BinderPrev is either: // binder_curried_inherit_base //for some Functor, or, it's another instance of this //template, preumably produced by this template's: // operator()(ArgNext arg_next) //member function. , typename ArgNow > struct binder_curried_inherit_next /**@brief * Binds ArgNow passed to CTOR to the BinderPrev::bounded+1 * argument of the Functor passed to binder_curried_inherit_base * superclass. */ : BinderPrev { typedef BinderPrev binder_prev ; typedef typename binder_prev::result_type result_type ; static unsigned const bounded =binder_prev::bounded+1 ; unsigned bounds(void)const { return bounded; } typedef ArgNow arg_now_type ; arg_now_type my_arg_now ; binder_curried_inherit_next ( binder_prev f //Superclass containing the Functor as well as //BinderPrev::bounded bounded arguments. , arg_now_type a_arg_now //value to be bound to the bounded-th argument of the //Functor stored in superclass. ) : binder_prev(f) , my_arg_now(a_arg_now) {} binder_curried_inherit_next ( binder_curried_inherit_next&& self ) : binder_prev(std::forward(self)) , my_arg_now(self.my_arg_now) {} typedef binder_curried_inherit_next < binder_prev , arg_now_type > binder_now ; template < typename ArgNext > binder_curried_inherit_next < binder_now , ArgNext > operator() ( ArgNext arg_next ) { typedef binder_curried_inherit_next < binder_now , ArgNext > binder_next ; return binder_next(*this,arg_next); } }; template < typename Functor //typename Functor is a functor, i.e. has //member function: // R operator()(typename... Args) //where R is Functor::maybe_result::type. > struct binder_curried_inherit_base : Functor { typedef typename Functor::result_type result_type ; static unsigned const bounded =0 ; virtual unsigned bounds(void)const { return bounded; } binder_curried_inherit_base ( Functor f ) : Functor(f) {} typedef binder_curried_inherit_base < Functor > binder_now ; template < typename ArgNext > binder_curried_inherit_next < binder_now , ArgNext > operator() ( ArgNext arg_next ) { typedef binder_curried_inherit_next < binder_now , ArgNext > binder_next ; return binder_next(*this,arg_next); } template < typename... BoundArgs > typename Functor::template maybe_result::type apply ( BoundArgs... bound_args ) { return Functor::operator()(bound_args...); } }; template < typename Binder , unsigned Index > struct at_bound_type_value /**@brief * Provides: * 1) type of Index-th bound argument of a Binder. * 2) method to retrieve value of Index-th bound argument to a Binder. */ : at_bound_type_value < typename Binder::binder_prev , Index-1 > {}; template < typename Binder > struct at_bound_type_value < Binder , 0 > { typedef typename Binder::arg_now_type type ; type value(Binder a_binder) { return a_binder.my_arg_now; } }; template < unsigned Index , typename Binder > struct at_bound_type : at_bound_type_value < Binder , Binder::bounded-Index-1 > {}; template < unsigned Index , typename Binder > typename at_bound_type < Index , Binder >::type at_bound_value ( Binder a_binder ) /**@brief * Returns the Index-th bounded value in a_binder. */ { at_bound_type_value at_bound_type_value_index; return at_bound_type_value_index.value(a_binder); } template < typename Binder , typename Result , unsigned... Indices > struct binder_result_indices ; struct nothing_result ; template < typename Binder , unsigned... Indices > struct binder_result_indices < Binder , nothing_result , Indices... > : Binder { binder_result_indices(Binder const& a_binder) : Binder(a_binder) {} }; template < typename Binder , typename Result , unsigned... Indices > struct binder_result_indices : binder_result_indices < Binder , nothing_result , Indices... > { typedef binder_result_indices < Binder , nothing_result , Indices... > super_type ; binder_result_indices(Binder const& a_binder) : super_type(a_binder) {} Result operator() ( void ) { Binder&self=*this; return self.apply ( at_bound_value(self)... ); } }; template < typename Binder , typename... Args > struct binder_args_result_type : Binder::template maybe_result {}; template < typename Binder , unsigned... Indices > struct binder_indices_result_type : binder_args_result_type < Binder , typename at_bound_type::type... > {}; template < typename Binder , unsigned... Indices > struct binder_indices_result_value : binder_result_indices < Binder , typename binder_indices_result_type < Binder , Indices... >::type , Indices... > { typedef binder_result_indices < Binder , typename binder_indices_result_type < Binder , Indices... >::type , Indices... > super_type ; binder_indices_result_value(Binder const& a_binder) : super_type(a_binder) {} }; template < typename Binder , templateclass BndrArgs , typename Indices > struct binder_indices_result ; template < typename Binder , templateclass BndrArgs , unsigned... Indices > struct binder_indices_result < Binder , BndrArgs , boost::mpl::package_c > : BndrArgs < Binder , Indices... > { typedef BndrArgs < Binder , Indices... > super_type ; binder_indices_result(Binder const& a_binder) : super_type(a_binder) {} }; template < typename Binder , unsigned... Indices > struct binder_indices_result < Binder , binder_indices_result_type , boost::mpl::package_c > : binder_indices_result_type < Binder , Indices... > { }; template < typename Binder > struct binder_result_type /**@brief * Metafunction returning the type of the result of * applying Binder to its bound arguments. */ : binder_indices_result < Binder , binder_indices_result_type , typename boost::mpl::package_range_c::type > { }; template < typename Binder > struct binder_result_value /**@brief * If Binder is "complete": * contains operator()() returning value of * applying Binder to its bound arguments. * Else: * is empty class. * Where: * a complete binder is one whose bound arguments * can be applied to Binder's contained functor. */ : binder_indices_result < Binder , binder_indices_result_value , typename boost::mpl::package_range_c::type > { typedef binder_indices_result < Binder , binder_indices_result_value , typename boost::mpl::package_range_c::type > super_type ; binder_result_value(Binder const& a_binder) : super_type(a_binder) {} }; template < typename Binder > typename Binder::result_type apply_bounded ( Binder const& a_binder ) { binder_result_value brv(a_binder); return brv(); } template < typename Functor > binder_curried_inherit_base curry_nullary ( Functor a_functor ) /**@brief * 'curries' a_functor to a functor, f, where: * f(a1)(a2)(a3)...(an)() * returns same result as: * a_functor(a1,a2,a3,...,an) */ { return binder_curried_inherit_base(a_functor); } #endif //BINDER_CURRIED_HPP_INCLUDED