/*============================================================================= Copyright (c) 2007-2008 Tobias Schwinger Use modification and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). ==============================================================================*/ #ifndef BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED # ifndef BOOST_PP_IS_ITERATING # include # include # include # include # include # include # include # include # ifndef BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY 6 # elif BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY < 3 # undef BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY 3 # endif namespace boost { template< typename Function, int Arity_Or_MinArity = -1, int MaxArity = -1 > class forward_adapter; //----- ---- --- -- - - - - namespace detail { template< class MostDerived, typename Function, typename FunctionConst, int Arity, int MinArity > struct forward_adapter_impl; struct forward_adapter_result { template< typename Sig > struct apply; // Utility metafunction for qualification adjustment on arguments template< typename T > struct q { typedef T const t; }; template< typename T > struct q { typedef T const t; }; template< typename T > struct q { typedef T t; }; // Utility metafunction to choose target function qualification template< typename T > struct c { typedef typename T::target_function_t t; }; template< typename T > struct c { typedef typename T::target_function_t t; }; template< typename T > struct c { typedef typename T::target_function_const_t t; }; template< typename T > struct c { typedef typename T::target_function_const_t t; }; }; } # define BOOST_TMP_MACRO(f,fn,fc) \ boost::detail::forward_adapter_impl< \ forward_adapter, fn, fc, \ (MaxArity!=-1? MaxArity :Arity_Or_MinArity!=-1? Arity_Or_MinArity \ :BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY), \ (Arity_Or_MinArity!=-1? Arity_Or_MinArity : 0) > template< typename Function, int Arity_Or_MinArity, int MaxArity > class forward_adapter : public BOOST_TMP_MACRO(Function,Function,Function const) , private Function { public: forward_adapter(Function const& f = Function()) : Function(f) { } typedef Function target_function_t; typedef Function const target_function_const_t; Function & target_function() { return *this; } Function const & target_function() const { return *this; } template< typename Sig > struct result : detail::forward_adapter_result::template apply { }; using BOOST_TMP_MACRO(Function,Function, Function const)::operator(); }; template< typename Function, int Arity_Or_MinArity, int MaxArity > class forward_adapter< Function const, Arity_Or_MinArity, MaxArity > : public BOOST_TMP_MACRO(Function const, Function const, Function const) , private Function { public: forward_adapter(Function const& f = Function()) : Function(f) { } typedef Function const target_function_t; typedef Function const target_function_const_t; Function const & target_function() const { return *this; } template< typename Sig > struct result : detail::forward_adapter_result::template apply { }; using BOOST_TMP_MACRO(Function const,Function const, Function const) ::operator(); }; template< typename Function, int Arity_Or_MinArity, int MaxArity > class forward_adapter< Function &, Arity_Or_MinArity, MaxArity > : public BOOST_TMP_MACRO(Function&, Function, Function) { Function& ref_function; public: forward_adapter(Function& f) : ref_function(f) { } typedef Function target_function_t; typedef Function target_function_const_t; Function & target_function() const { return this->ref_function; } template< typename Sig > struct result : detail::forward_adapter_result::template apply { }; using BOOST_TMP_MACRO(Function&, Function, Function)::operator(); }; #undef BOOST_TMP_MACRO namespace detail { template< class Self > struct forward_adapter_result::apply< Self() > : boost::result_of< BOOST_DEDUCED_TYPENAME c::t() > { }; template< class MD, class F, class FC > struct forward_adapter_impl { inline typename boost::result_of< FC() >::type operator()() const { return static_cast(this)->target_function()(); } inline typename boost::result_of< F() >::type operator()() { return static_cast(this)->target_function()(); } // closing brace gets generated by preprocessing code, below # define BOOST_TMP_MACRO(tpl_params,arg_types,params,args) \ template< tpl_params > \ inline typename boost::result_of< FC(arg_types) >::type \ operator()(params) const \ { \ return static_cast(this)->target_function()(args); \ } \ template< tpl_params > \ inline typename boost::result_of< F(arg_types)>::type \ operator()(params) \ { \ return static_cast(this)->target_function()(args); \ } # // This is the total number of iterations we need # define count ((1 << BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY+1)-2) # // Chain file iteration to virtually one loop # if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 7 # define limit1 count # define limit2 0 # define limit3 0 # else # if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 15 # define limit1 (count >> 8) # define limit2 255 # define limit3 0 # else # define limit1 (count >> 16) # define limit2 255 # define limit3 255 # endif # endif # define N 0 # define BOOST_PP_FILENAME_1 # define BOOST_PP_ITERATION_LIMITS (0,limit1) # include BOOST_PP_ITERATE() # undef N # undef limit3 # undef limit2 # undef limit1 # undef count # undef BOOST_TMP_MACRO }; } // namespace detail template struct result_of const ()> : boost::detail::forward_adapter_result::template apply< boost::forward_adapter const () > { }; template struct result_of()> : boost::detail::forward_adapter_result::template apply< boost::forward_adapter() > { }; template struct result_of const& ()> : boost::detail::forward_adapter_result::template apply< boost::forward_adapter const () > { }; template struct result_of& ()> : boost::detail::forward_adapter_result::template apply< boost::forward_adapter() > { }; } # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED # elif BOOST_PP_ITERATION_DEPTH() == 1 && limit2 # define BOOST_PP_FILENAME_2 # define BOOST_PP_ITERATION_LIMITS (0,limit2) # include BOOST_PP_ITERATE() # elif BOOST_PP_ITERATION_DEPTH() == 2 && limit3 # define BOOST_PP_FILENAME_3 # define BOOST_PP_ITERATION_LIMITS (0,limit3) # include BOOST_PP_ITERATE() # else # // I is the loop counter # if limit2 && limit3 # define I (BOOST_PP_ITERATION_1 << 16 | BOOST_PP_ITERATION_2 << 8 | \ BOOST_PP_ITERATION_3) # elif limit2 # define I (BOOST_PP_ITERATION_1 << 8 | BOOST_PP_ITERATION_2) # else # define I BOOST_PP_ITERATION_1 # endif # if I < count # // Done for this arity? Increment N # if (I+2 >> N+1) # if N == 0 # undef N # define N 1 # elif N == 1 # undef N # define N 2 # elif N == 2 # undef N # define N 3 # elif N == 3 # undef N # define N 4 # elif N == 4 # undef N # define N 5 # elif N == 5 # undef N # define N 6 # elif N == 6 # undef N # define N 7 # elif N == 7 # undef N # define N 8 # elif N == 8 # undef N # define N 9 # elif N == 9 # undef N # define N 10 # elif N == 10 # undef N # define N 11 # elif N == 11 # undef N # define N 12 # elif N == 12 # undef N # define N 13 # elif N == 13 # undef N # define N 14 # elif N == 14 # undef N # define N 15 # elif N == 15 # undef N # define N 16 # endif }; template< class Self, BOOST_PP_ENUM_PARAMS(N,typename T) > struct forward_adapter_result::apply< Self(BOOST_PP_ENUM_PARAMS(N,T)) > : boost::result_of< BOOST_DEDUCED_TYPENAME c::t(BOOST_PP_ENUM_BINARY_PARAMS(N, typename q::t& BOOST_PP_INTERCEPT)) > { }; template< class MD, class F, class FC > struct forward_adapter_impl { template< BOOST_PP_ENUM_PARAMS(N,typename T) > inline typename boost::result_of< F( BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)) >::type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)); }; template< class MD, class F, class FC, int MinArity > struct forward_adapter_impl : forward_adapter_impl { using forward_adapter_impl::operator(); # endif # // Zero based count for each arity would be I-(1< inline typename boost::result_of< FC(BOOST_PP_ENUM_PARAMS(N,PT)) >::type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) const { return static_cast(this) ->target_function()(BOOST_PP_ENUM_PARAMS(N,a)); } template< BOOST_PP_ENUM_PARAMS(N,typename T) > inline typename boost::result_of< F(BOOST_PP_ENUM_PARAMS(N,PT)) >::type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) { return static_cast(this) ->target_function()(BOOST_PP_ENUM_PARAMS(N,a)); } # else BOOST_TMP_MACRO(BOOST_PP_ENUM_PARAMS(N,typename T), BOOST_PP_ENUM_PARAMS(N,PT), BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a), BOOST_PP_ENUM_PARAMS(N,a) ) // ...generates uglier code but is faster - it caches ENUM_* # endif # undef PT0 # undef PT1 # undef PT2 # undef PT3 # undef PT4 # undef PT5 # undef PT6 # undef PT7 # undef PT8 # undef PT9 # undef PT10 # undef PT11 # undef PT12 # undef PT13 # undef PT14 # undef PT15 # endif // I < count # undef I # endif // defined(BOOST_PP_IS_ITERATING) #endif // include guard