1 /*=============================================================================
2 Copyright (c) 2007-2008 Tobias Schwinger
4 Use modification and distribution are subject to the Boost Software
5 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt).
7 ==============================================================================*/
9 #ifndef BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED
10 # ifndef BOOST_PP_IS_ITERATING
12 # include <boost/config.hpp>
13 # include <boost/detail/workaround.hpp>
15 # include <boost/preprocessor/iteration/iterate.hpp>
16 # include <boost/preprocessor/repetition/enum_params.hpp>
17 # include <boost/preprocessor/repetition/enum_binary_params.hpp>
18 # include <boost/preprocessor/facilities/intercept.hpp>
19 # include <boost/preprocessor/arithmetic/dec.hpp>
21 # include <boost/utility/result_of.hpp>
23 # ifndef BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY
24 # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY 6
25 # elif BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY < 3
26 # undef BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY
27 # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY 3
33 template< typename Function, int Arity_Or_MinArity = -1, int MaxArity = -1 >
34 class forward_adapter;
36 //----- ---- --- -- - - - -
40 template< class MostDerived, typename Function, typename FunctionConst,
41 int Arity, int MinArity >
42 struct forward_adapter_impl;
44 struct forward_adapter_result
46 template< typename Sig > struct apply;
48 // Utility metafunction for qualification adjustment on arguments
49 template< typename T > struct q { typedef T const t; };
50 template< typename T > struct q<T const> { typedef T const t; };
51 template< typename T > struct q<T &> { typedef T t; };
53 // Utility metafunction to choose target function qualification
54 template< typename T > struct c
55 { typedef typename T::target_function_t t; };
56 template< typename T > struct c<T& >
57 { typedef typename T::target_function_t t; };
58 template< typename T > struct c<T const >
59 { typedef typename T::target_function_const_t t; };
60 template< typename T > struct c<T const&>
61 { typedef typename T::target_function_const_t t; };
65 # define BOOST_TMP_MACRO(f,fn,fc) \
66 boost::detail::forward_adapter_impl< \
67 forward_adapter<f,Arity_Or_MinArity,MaxArity>, fn, fc, \
68 (MaxArity!=-1? MaxArity :Arity_Or_MinArity!=-1? Arity_Or_MinArity \
69 :BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY), \
70 (Arity_Or_MinArity!=-1? Arity_Or_MinArity : 0) >
72 template< typename Function, int Arity_Or_MinArity, int MaxArity >
74 : public BOOST_TMP_MACRO(Function,Function,Function const)
78 forward_adapter(Function const& f = Function())
82 typedef Function target_function_t;
83 typedef Function const target_function_const_t;
85 Function & target_function() { return *this; }
86 Function const & target_function() const { return *this; }
88 template< typename Sig > struct result
89 : detail::forward_adapter_result::template apply<Sig>
92 using BOOST_TMP_MACRO(Function,Function, Function const)::operator();
94 template< typename Function, int Arity_Or_MinArity, int MaxArity >
95 class forward_adapter< Function const, Arity_Or_MinArity, MaxArity >
96 : public BOOST_TMP_MACRO(Function const, Function const, Function const)
100 forward_adapter(Function const& f = Function())
104 typedef Function const target_function_t;
105 typedef Function const target_function_const_t;
107 Function const & target_function() const { return *this; }
109 template< typename Sig > struct result
110 : detail::forward_adapter_result::template apply<Sig>
113 using BOOST_TMP_MACRO(Function const,Function const, Function const)
116 template< typename Function, int Arity_Or_MinArity, int MaxArity >
117 class forward_adapter< Function &, Arity_Or_MinArity, MaxArity >
118 : public BOOST_TMP_MACRO(Function&, Function, Function)
120 Function& ref_function;
122 forward_adapter(Function& f)
126 typedef Function target_function_t;
127 typedef Function target_function_const_t;
129 Function & target_function() const { return this->ref_function; }
131 template< typename Sig > struct result
132 : detail::forward_adapter_result::template apply<Sig>
135 using BOOST_TMP_MACRO(Function&, Function, Function)::operator();
138 #undef BOOST_TMP_MACRO
142 template< class Self >
143 struct forward_adapter_result::apply< Self() >
144 : boost::result_of< BOOST_DEDUCED_TYPENAME c<Self>::t() >
147 // WHen operator()() doesn't have any parameters, it can't
148 // be templatized and can't use SFINAE, so intead use class
149 // template parameter SFINAE to decide whether to instantiate it.
151 template <typename T, typename R = void>
152 struct forward_adapter_sfinae
157 // This is the fallback for when there isn't an operator()(),
158 // need to create an operator() that will never instantiate
159 // so that using parent::operator() will work okay.
160 template< class MD, class F, class FC, class Enable = void>
161 struct forward_adapter_impl_zero
163 template <typename T> struct never_instantiate {};
164 template <typename T>
165 typename never_instantiate<T>::type operator()(T) const {}
168 template< class MD, class F, class FC>
169 struct forward_adapter_impl_zero<MD, F, FC,
170 typename forward_adapter_sfinae<typename boost::result_of< FC() >::type>::type>
172 inline typename boost::result_of< FC() >::type
175 return static_cast<MD const*>(this)->target_function()();
178 inline typename boost::result_of< F() >::type
181 return static_cast<MD*>(this)->target_function()();
185 template< class MD, class F, class FC >
186 struct forward_adapter_impl<MD,F,FC,0,0>
187 : forward_adapter_impl_zero<MD,F,FC>
189 using forward_adapter_impl_zero<MD,F,FC>::operator();
191 // closing brace gets generated by preprocessing code, below
193 # define BOOST_TMP_MACRO(tpl_params,arg_types,params,args) \
194 template< tpl_params > \
195 inline typename boost::result_of< FC(arg_types) >::type \
196 operator()(params) const \
198 return static_cast<MD const*>(this)->target_function()(args); \
200 template< tpl_params > \
201 inline typename boost::result_of< F(arg_types)>::type \
204 return static_cast<MD*>(this)->target_function()(args); \
207 # // This is the total number of iterations we need
208 # define count ((1 << BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY+1)-2)
210 # // Chain file iteration to virtually one loop
211 # if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 7
212 # define limit1 count
216 # if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 15
217 # define limit1 (count >> 8)
221 # define limit1 (count >> 16)
229 # define BOOST_PP_FILENAME_1 <boost/functional/forward_adapter.hpp>
230 # define BOOST_PP_ITERATION_LIMITS (0,limit1)
231 # include BOOST_PP_ITERATE()
238 # undef BOOST_TMP_MACRO
242 } // namespace detail
244 template<class F, int A0, int A1>
245 struct result_of<boost::forward_adapter<F,A0,A1> const ()>
246 : boost::detail::forward_adapter_result::template apply<
247 boost::forward_adapter<F,A0,A1> const () >
249 template<class F, int A0, int A1>
250 struct result_of<boost::forward_adapter<F,A0,A1>()>
251 : boost::detail::forward_adapter_result::template apply<
252 boost::forward_adapter<F,A0,A1>() >
254 template<class F, int A0, int A1>
255 struct result_of<boost::forward_adapter<F,A0,A1> const& ()>
256 : boost::detail::forward_adapter_result::template apply<
257 boost::forward_adapter<F,A0,A1> const () >
259 template<class F, int A0, int A1>
260 struct result_of<boost::forward_adapter<F,A0,A1>& ()>
261 : boost::detail::forward_adapter_result::template apply<
262 boost::forward_adapter<F,A0,A1>() >
266 # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED
268 # elif BOOST_PP_ITERATION_DEPTH() == 1 && limit2
269 # define BOOST_PP_FILENAME_2 <boost/functional/forward_adapter.hpp>
270 # define BOOST_PP_ITERATION_LIMITS (0,limit2)
271 # include BOOST_PP_ITERATE()
272 # elif BOOST_PP_ITERATION_DEPTH() == 2 && limit3
273 # define BOOST_PP_FILENAME_3 <boost/functional/forward_adapter.hpp>
274 # define BOOST_PP_ITERATION_LIMITS (0,limit3)
275 # include BOOST_PP_ITERATE()
279 # // I is the loop counter
280 # if limit2 && limit3
281 # define I (BOOST_PP_ITERATION_1 << 16 | BOOST_PP_ITERATION_2 << 8 | \
282 BOOST_PP_ITERATION_3)
284 # define I (BOOST_PP_ITERATION_1 << 8 | BOOST_PP_ITERATION_2)
286 # define I BOOST_PP_ITERATION_1
291 # // Done for this arity? Increment N
345 template< class Self, BOOST_PP_ENUM_PARAMS(N,typename T) >
346 struct forward_adapter_result::apply< Self(BOOST_PP_ENUM_PARAMS(N,T)) >
348 BOOST_DEDUCED_TYPENAME c<Self>::t(BOOST_PP_ENUM_BINARY_PARAMS(N,
349 typename q<T,>::t& BOOST_PP_INTERCEPT)) >
352 template< class MD, class F, class FC >
353 struct forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),N>
355 template< BOOST_PP_ENUM_PARAMS(N,typename T) >
356 inline typename boost::result_of< F(
357 BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)) >::type
358 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT));
361 template< class MD, class F, class FC, int MinArity >
362 struct forward_adapter_impl<MD,F,FC,N,MinArity>
363 : forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>
365 using forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>::operator();
369 # // Zero based count for each arity would be I-(1<<N)+2, but we don't
370 # // need it, unless we need a nicer order.
372 # // Macros for the parameter's type modifiers.
376 # define PT0 T0 const &
381 # define PT1 T1 const &
386 # define PT2 T2 const &
391 # define PT3 T3 const &
396 # define PT4 T4 const &
401 # define PT5 T5 const &
406 # define PT6 T6 const &
411 # define PT7 T7 const &
416 # define PT8 T8 const &
421 # define PT9 T9 const &
426 # define PT10 T10 const &
431 # define PT11 T11 const &
436 # define PT12 T12 const &
441 # define PT13 T13 const &
446 # define PT14 T14 const &
451 # define PT15 T15 const &
454 # if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
455 template< BOOST_PP_ENUM_PARAMS(N,typename T) >
456 inline typename boost::result_of< FC(BOOST_PP_ENUM_PARAMS(N,PT))
458 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) const
460 return static_cast<MD const* const>(this)
461 ->target_function()(BOOST_PP_ENUM_PARAMS(N,a));
463 template< BOOST_PP_ENUM_PARAMS(N,typename T) >
464 inline typename boost::result_of< F(BOOST_PP_ENUM_PARAMS(N,PT))
466 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a))
468 return static_cast<MD* const>(this)
469 ->target_function()(BOOST_PP_ENUM_PARAMS(N,a));
472 BOOST_TMP_MACRO(BOOST_PP_ENUM_PARAMS(N,typename T),
473 BOOST_PP_ENUM_PARAMS(N,PT), BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a),
474 BOOST_PP_ENUM_PARAMS(N,a) )
475 // ...generates uglier code but is faster - it caches ENUM_*
498 # endif // defined(BOOST_PP_IS_ITERATING)
500 #endif // include guard