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 
31 namespace 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:
forward_adapter(Function const & f=Function ())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 
target_function()85         Function       & target_function()       { return *this; }
target_function() const86         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:
forward_adapter(Function const & f=Function ())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 
target_function() const107         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:
forward_adapter(Function & f)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 
target_function() const129         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
operator ()boost::detail::forward_adapter_impl151             operator()() const
152             {
153                 return static_cast<MD const*>(this)->target_function()();
154             }
155 
156             inline typename boost::result_of< F() >::type
operator ()boost::detail::forward_adapter_impl157             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