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
< typename c
<Self
>::t() >
147 template< class MD
, class F
, class FC
>
148 struct forward_adapter_impl
<MD
,F
,FC
,0,0>
150 inline typename
boost::result_of
< FC() >::type
153 return static_cast<MD
const*>(this)->target_function()();
156 inline typename
boost::result_of
< F() >::type
159 return static_cast<MD
*>(this)->target_function()();
162 // closing brace gets generated by preprocessing code, below
164 # define BOOST_TMP_MACRO(tpl_params,arg_types,params,args) \
165 template< tpl_params > \
166 inline typename boost::result_of< FC(arg_types) >::type \
167 operator()(params) const \
169 return static_cast<MD const*>(this)->target_function()(args); \
171 template< tpl_params > \
172 inline typename boost::result_of< F(arg_types)>::type \
175 return static_cast<MD*>(this)->target_function()(args); \
178 # // This is the total number of iterations we need
179 # define count ((1 << BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY+1)-2)
181 # // Chain file iteration to virtually one loop
182 # if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 7
183 # define limit1 count
187 # if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 15
188 # define limit1 (count >> 8)
192 # define limit1 (count >> 16)
200 # define BOOST_PP_FILENAME_1 <boost/functional/forward_adapter.hpp>
201 # define BOOST_PP_ITERATION_LIMITS (0,limit1)
202 # include BOOST_PP_ITERATE()
209 # undef BOOST_TMP_MACRO
213 } // namespace detail
215 template<class F
, int A0
, int A1
>
216 struct result_of
<boost::forward_adapter
<F
,A0
,A1
> const ()>
217 : boost::detail::forward_adapter_result::template apply
<
218 boost::forward_adapter
<F
,A0
,A1
> const () >
220 template<class F
, int A0
, int A1
>
221 struct result_of
<boost::forward_adapter
<F
,A0
,A1
>()>
222 : boost::detail::forward_adapter_result::template apply
<
223 boost::forward_adapter
<F
,A0
,A1
>() >
225 template<class F
, int A0
, int A1
>
226 struct result_of
<boost::forward_adapter
<F
,A0
,A1
> const& ()>
227 : boost::detail::forward_adapter_result::template apply
<
228 boost::forward_adapter
<F
,A0
,A1
> const () >
230 template<class F
, int A0
, int A1
>
231 struct result_of
<boost::forward_adapter
<F
,A0
,A1
>& ()>
232 : boost::detail::forward_adapter_result::template apply
<
233 boost::forward_adapter
<F
,A0
,A1
>() >
237 # define BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED
239 # elif BOOST_PP_ITERATION_DEPTH() == 1 && limit2
240 # define BOOST_PP_FILENAME_2 <boost/functional/forward_adapter.hpp>
241 # define BOOST_PP_ITERATION_LIMITS (0,limit2)
242 # include BOOST_PP_ITERATE()
243 # elif BOOST_PP_ITERATION_DEPTH() == 2 && limit3
244 # define BOOST_PP_FILENAME_3 <boost/functional/forward_adapter.hpp>
245 # define BOOST_PP_ITERATION_LIMITS (0,limit3)
246 # include BOOST_PP_ITERATE()
250 # // I is the loop counter
251 # if limit2 && limit3
252 # define I (BOOST_PP_ITERATION_1 << 16 | BOOST_PP_ITERATION_2 << 8 | \
253 BOOST_PP_ITERATION_3)
255 # define I (BOOST_PP_ITERATION_1 << 8 | BOOST_PP_ITERATION_2)
257 # define I BOOST_PP_ITERATION_1
262 # // Done for this arity? Increment N
316 template< class Self
, BOOST_PP_ENUM_PARAMS(N
,typename T
) >
317 struct forward_adapter_result::apply
< Self(BOOST_PP_ENUM_PARAMS(N
,T
)) >
319 typename c
<Self
>::t(BOOST_PP_ENUM_BINARY_PARAMS(N
,
320 typename q
<T
,>::t
& BOOST_PP_INTERCEPT
)) >
323 template< class MD
, class F
, class FC
>
324 struct forward_adapter_impl
<MD
,F
,FC
,BOOST_PP_DEC(N
),N
>
326 template< BOOST_PP_ENUM_PARAMS(N
,typename T
) >
327 inline typename
boost::result_of
< F(
328 BOOST_PP_ENUM_BINARY_PARAMS(N
,T
,& BOOST_PP_INTERCEPT
)) >::type
329 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N
,T
,& BOOST_PP_INTERCEPT
));
332 template< class MD
, class F
, class FC
, int MinArity
>
333 struct forward_adapter_impl
<MD
,F
,FC
,N
,MinArity
>
334 : forward_adapter_impl
<MD
,F
,FC
,BOOST_PP_DEC(N
),MinArity
>
336 using forward_adapter_impl
<MD
,F
,FC
,BOOST_PP_DEC(N
),MinArity
>::operator();
340 # // Zero based count for each arity would be I-(1<<N)+2, but we don't
341 # // need it, unless we need a nicer order.
343 # // Macros for the parameter's type modifiers.
347 # define PT0 T0 const &
352 # define PT1 T1 const &
357 # define PT2 T2 const &
362 # define PT3 T3 const &
367 # define PT4 T4 const &
372 # define PT5 T5 const &
377 # define PT6 T6 const &
382 # define PT7 T7 const &
387 # define PT8 T8 const &
392 # define PT9 T9 const &
397 # define PT10 T10 const &
402 # define PT11 T11 const &
407 # define PT12 T12 const &
412 # define PT13 T13 const &
417 # define PT14 T14 const &
422 # define PT15 T15 const &
425 # if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
426 template< BOOST_PP_ENUM_PARAMS(N
,typename T
) >
427 inline typename
boost::result_of
< FC(BOOST_PP_ENUM_PARAMS(N
,PT
))
429 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N
,PT
,a
)) const
431 return static_cast<MD
const* const>(this)
432 ->target_function()(BOOST_PP_ENUM_PARAMS(N
,a
));
434 template< BOOST_PP_ENUM_PARAMS(N
,typename T
) >
435 inline typename
boost::result_of
< F(BOOST_PP_ENUM_PARAMS(N
,PT
))
437 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N
,PT
,a
))
439 return static_cast<MD
* const>(this)
440 ->target_function()(BOOST_PP_ENUM_PARAMS(N
,a
));
443 BOOST_TMP_MACRO(BOOST_PP_ENUM_PARAMS(N
,typename T
),
444 BOOST_PP_ENUM_PARAMS(N
,PT
), BOOST_PP_ENUM_BINARY_PARAMS(N
,PT
,a
),
445 BOOST_PP_ENUM_PARAMS(N
,a
) )
446 // ...generates uglier code but is faster - it caches ENUM_*
469 # endif // defined(BOOST_PP_IS_ITERATING)
471 #endif // include guard