1/*=============================================================================
2 Copyright (c) 2007-2008 Tobias Schwinger
3
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==============================================================================*/
8
9#ifndef BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED
10# ifndef BOOST_PP_IS_ITERATING
11
12# include <boost/config.hpp>
13# include <boost/detail/workaround.hpp>
14
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>
20
21# include <boost/utility/result_of.hpp>
22
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
28# endif
29
30
31namespace boost
32{
33 template< typename Function, int Arity_Or_MinArity = -1, int MaxArity = -1 >
34 class forward_adapter;
35
36 //----- ---- --- -- - - - -
37
38 namespace detail
39 {
40 template< class MostDerived, typename Function, typename FunctionConst,
41 int Arity, int MinArity >
42 struct forward_adapter_impl;
43
44 struct forward_adapter_result
45 {
46 template< typename Sig > struct apply;
47
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; };
52
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; };
62 };
63 }
64
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) >
71
72 template< typename Function, int Arity_Or_MinArity, int MaxArity >
73 class forward_adapter
74 : public BOOST_TMP_MACRO(Function,Function,Function const)
75 , private Function
76 {
77 public:
78 forward_adapter(Function const& f = Function())
79 : Function(f)
80 { }
81
82 typedef Function target_function_t;
83 typedef Function const target_function_const_t;
84
85 Function & target_function() { return *this; }
86 Function const & target_function() const { return *this; }
87
88 template< typename Sig > struct result
89 : detail::forward_adapter_result::template apply<Sig>
90 { };
91
92 using BOOST_TMP_MACRO(Function,Function, Function const)::operator();
93 };
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)
97 , private Function
98 {
99 public:
100 forward_adapter(Function const& f = Function())
101 : Function(f)
102 { }
103
104 typedef Function const target_function_t;
105 typedef Function const target_function_const_t;
106
107 Function const & target_function() const { return *this; }
108
109 template< typename Sig > struct result
110 : detail::forward_adapter_result::template apply<Sig>
111 { };
112
113 using BOOST_TMP_MACRO(Function const,Function const, Function const)
114 ::operator();
115 };
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)
119 {
120 Function& ref_function;
121 public:
122 forward_adapter(Function& f)
123 : ref_function(f)
124 { }
125
126 typedef Function target_function_t;
127 typedef Function target_function_const_t;
128
129 Function & target_function() const { return this->ref_function; }
130
131 template< typename Sig > struct result
132 : detail::forward_adapter_result::template apply<Sig>
133 { };
134
135 using BOOST_TMP_MACRO(Function&, Function, Function)::operator();
136 };
137
138 #undef BOOST_TMP_MACRO
139
140 namespace detail
141 {
142 template< class Self >
143 struct forward_adapter_result::apply< Self() >
144 : boost::result_of< BOOST_DEDUCED_TYPENAME c<Self>::t() >
145 { };
146
147 template< class MD, class F, class FC >
148 struct forward_adapter_impl<MD,F,FC,0,0>
149 {
150 inline typename boost::result_of< FC() >::type
151 operator()() const
152 {
153 return static_cast<MD const*>(this)->target_function()();
154 }
155
156 inline typename boost::result_of< F() >::type
157 operator()()
158 {
159 return static_cast<MD*>(this)->target_function()();
160 }
161
162 // closing brace gets generated by preprocessing code, below
163
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 \
168 { \
169 return static_cast<MD const*>(this)->target_function()(args); \
170 } \
171 template< tpl_params > \
172 inline typename boost::result_of< F(arg_types)>::type \
173 operator()(params) \
174 { \
175 return static_cast<MD*>(this)->target_function()(args); \
176 }
177
178# // This is the total number of iterations we need
179# define count ((1 << BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY+1)-2)
180
181# // Chain file iteration to virtually one loop
182# if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 7
183# define limit1 count
184# define limit2 0
185# define limit3 0
186# else
187# if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 15
188# define limit1 (count >> 8)
189# define limit2 255
190# define limit3 0
191# else
192# define limit1 (count >> 16)
193# define limit2 255
194# define limit3 255
195# endif
196# endif
197
198# define N 0
199
200# define BOOST_PP_FILENAME_1 <boost/functional/forward_adapter.hpp>
201# define BOOST_PP_ITERATION_LIMITS (0,limit1)
202# include BOOST_PP_ITERATE()
203
204# undef N
205# undef limit3
206# undef limit2
207# undef limit1
208# undef count
209# undef BOOST_TMP_MACRO
210
211 };
212
213 } // namespace detail
214
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 () >
219 { };
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>() >
224 { };
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 () >
229 { };
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>() >
234 { };
235}
236
237# define BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED
238
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()
247
248# else
249
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)
254# elif limit2
255# define I (BOOST_PP_ITERATION_1 << 8 | BOOST_PP_ITERATION_2)
256# else
257# define I BOOST_PP_ITERATION_1
258# endif
259
260# if I < count
261
262# // Done for this arity? Increment N
263# if (I+2 >> N+1)
264# if N == 0
265# undef N
266# define N 1
267# elif N == 1
268# undef N
269# define N 2
270# elif N == 2
271# undef N
272# define N 3
273# elif N == 3
274# undef N
275# define N 4
276# elif N == 4
277# undef N
278# define N 5
279# elif N == 5
280# undef N
281# define N 6
282# elif N == 6
283# undef N
284# define N 7
285# elif N == 7
286# undef N
287# define N 8
288# elif N == 8
289# undef N
290# define N 9
291# elif N == 9
292# undef N
293# define N 10
294# elif N == 10
295# undef N
296# define N 11
297# elif N == 11
298# undef N
299# define N 12
300# elif N == 12
301# undef N
302# define N 13
303# elif N == 13
304# undef N
305# define N 14
306# elif N == 14
307# undef N
308# define N 15
309# elif N == 15
310# undef N
311# define N 16
312# endif
313
314 };
315
316 template< class Self, BOOST_PP_ENUM_PARAMS(N,typename T) >
317 struct forward_adapter_result::apply< Self(BOOST_PP_ENUM_PARAMS(N,T)) >
318 : boost::result_of<
319 BOOST_DEDUCED_TYPENAME c<Self>::t(BOOST_PP_ENUM_BINARY_PARAMS(N,
320 typename q<T,>::t& BOOST_PP_INTERCEPT)) >
321 { };
322
323 template< class MD, class F, class FC >
324 struct forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),N>
325 {
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));
330 };
331
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>
335 {
336 using forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>::operator();
337
338# endif
339
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.
342
343# // Macros for the parameter's type modifiers.
344# if I & 0x000001
345# define PT0 T0 &
346# else
347# define PT0 T0 const &
348# endif
349# if I & 0x000002
350# define PT1 T1 &
351# else
352# define PT1 T1 const &
353# endif
354# if I & 0x000004
355# define PT2 T2 &
356# else
357# define PT2 T2 const &
358# endif
359# if I & 0x000008
360# define PT3 T3 &
361# else
362# define PT3 T3 const &
363# endif
364# if I & 0x000010
365# define PT4 T4 &
366# else
367# define PT4 T4 const &
368# endif
369# if I & 0x000020
370# define PT5 T5 &
371# else
372# define PT5 T5 const &
373# endif
374# if I & 0x000040
375# define PT6 T6 &
376# else
377# define PT6 T6 const &
378# endif
379# if I & 0x000080
380# define PT7 T7 &
381# else
382# define PT7 T7 const &
383# endif
384# if I & 0x000100
385# define PT8 T8 &
386# else
387# define PT8 T8 const &
388# endif
389# if I & 0x000200
390# define PT9 T9 &
391# else
392# define PT9 T9 const &
393# endif
394# if I & 0x000400
395# define PT10 T10 &
396# else
397# define PT10 T10 const &
398# endif
399# if I & 0x000800
400# define PT11 T11 &
401# else
402# define PT11 T11 const &
403# endif
404# if I & 0x001000
405# define PT12 T12 &
406# else
407# define PT12 T12 const &
408# endif
409# if I & 0x002000
410# define PT13 T13 &
411# else
412# define PT13 T13 const &
413# endif
414# if I & 0x004000
415# define PT14 T14 &
416# else
417# define PT14 T14 const &
418# endif
419# if I & 0x008000
420# define PT15 T15 &
421# else
422# define PT15 T15 const &
423# endif
424
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))
428 >::type
429 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) const
430 {
431 return static_cast<MD const* const>(this)
432 ->target_function()(BOOST_PP_ENUM_PARAMS(N,a));
433 }
434 template< BOOST_PP_ENUM_PARAMS(N,typename T) >
435 inline typename boost::result_of< F(BOOST_PP_ENUM_PARAMS(N,PT))
436 >::type
437 operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a))
438 {
439 return static_cast<MD* const>(this)
440 ->target_function()(BOOST_PP_ENUM_PARAMS(N,a));
441 }
442# else
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_*
447# endif
448
449# undef PT0
450# undef PT1
451# undef PT2
452# undef PT3
453# undef PT4
454# undef PT5
455# undef PT6
456# undef PT7
457# undef PT8
458# undef PT9
459# undef PT10
460# undef PT11
461# undef PT12
462# undef PT13
463# undef PT14
464# undef PT15
465
466# endif // I < count
467
468# undef I
469# endif // defined(BOOST_PP_IS_ITERATING)
470
471#endif // include guard
472
473

source code of boost/boost/functional/forward_adapter.hpp