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/config/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         // 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.
150 
151         template <typename T, typename R = void>
152         struct forward_adapter_sfinae
153         {
154             typedef T type;
155         };
156 
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
162         {
163             template <typename T> struct never_instantiate {};
164             template <typename T>
operator ()boost::detail::forward_adapter_impl_zero165             typename never_instantiate<T>::type operator()(T) const {}
166         };
167 
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>
171         {
172             inline typename boost::result_of< FC() >::type
operator ()boost::detail::forward_adapter_impl_zero173             operator()() const
174             {
175                 return static_cast<MD const*>(this)->target_function()();
176             }
177 
178             inline typename boost::result_of< F() >::type
operator ()boost::detail::forward_adapter_impl_zero179             operator()()
180             {
181                 return static_cast<MD*>(this)->target_function()();
182             }
183         };
184 
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>
188         {
189             using forward_adapter_impl_zero<MD,F,FC>::operator();
190 
191         // closing brace gets generated by preprocessing code, below
192 
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                                           \
197             {                                                                  \
198                 return static_cast<MD const*>(this)->target_function()(args);  \
199             }                                                                  \
200             template< tpl_params >                                             \
201             inline typename boost::result_of< F(arg_types)>::type              \
202             operator()(params)                                                 \
203             {                                                                  \
204                 return static_cast<MD*>(this)->target_function()(args);        \
205             }
206 
207 #       // This is the total number of iterations we need
208 #       define count ((1 << BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY+1)-2)
209 
210 #       // Chain file iteration to virtually one loop
211 #       if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 7
212 #         define limit1 count
213 #         define limit2 0
214 #         define limit3 0
215 #       else
216 #         if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 15
217 #           define limit1 (count >> 8)
218 #           define limit2 255
219 #           define limit3 0
220 #         else
221 #           define limit1 (count >> 16)
222 #           define limit2 255
223 #           define limit3 255
224 #         endif
225 #       endif
226 
227 #       define N 0
228 
229 #       define  BOOST_PP_FILENAME_1 <boost/functional/forward_adapter.hpp>
230 #       define  BOOST_PP_ITERATION_LIMITS (0,limit1)
231 #       include BOOST_PP_ITERATE()
232 
233 #       undef N
234 #       undef limit3
235 #       undef limit2
236 #       undef limit1
237 #       undef count
238 #       undef BOOST_TMP_MACRO
239 
240         };
241 
242     } // namespace detail
243 
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 () >
248     { };
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>() >
253     { };
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 () >
258     { };
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>() >
263     { };
264 }
265 
266 #       define BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED
267 
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()
276 
277 #   else
278 
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)
283 #     elif limit2
284 #       define I (BOOST_PP_ITERATION_1 << 8 | BOOST_PP_ITERATION_2)
285 #     else
286 #       define I BOOST_PP_ITERATION_1
287 #     endif
288 
289 #     if I < count
290 
291 #       // Done for this arity? Increment N
292 #       if (I+2 >> N+1)
293 #         if N == 0
294 #           undef N
295 #           define N 1
296 #         elif N == 1
297 #           undef N
298 #           define N 2
299 #         elif N == 2
300 #           undef N
301 #           define N 3
302 #         elif N == 3
303 #           undef N
304 #           define N 4
305 #         elif N == 4
306 #           undef N
307 #           define N 5
308 #         elif N == 5
309 #           undef N
310 #           define N 6
311 #         elif N == 6
312 #           undef N
313 #           define N 7
314 #         elif N == 7
315 #           undef N
316 #           define N 8
317 #         elif N == 8
318 #           undef N
319 #           define N 9
320 #         elif N == 9
321 #           undef N
322 #           define N 10
323 #         elif N == 10
324 #           undef N
325 #           define N 11
326 #         elif N == 11
327 #           undef N
328 #           define N 12
329 #         elif N == 12
330 #           undef N
331 #           define N 13
332 #         elif N == 13
333 #           undef N
334 #           define N 14
335 #         elif N == 14
336 #           undef N
337 #           define N 15
338 #         elif N == 15
339 #           undef N
340 #           define N 16
341 #         endif
342 
343         };
344 
345         template< class Self, BOOST_PP_ENUM_PARAMS(N,typename T) >
346         struct forward_adapter_result::apply< Self(BOOST_PP_ENUM_PARAMS(N,T)) >
347             : boost::result_of<
348                 BOOST_DEDUCED_TYPENAME c<Self>::t(BOOST_PP_ENUM_BINARY_PARAMS(N,
349                       typename q<T,>::t& BOOST_PP_INTERCEPT)) >
350         { };
351 
352         template< class MD, class F, class FC >
353         struct forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),N>
354         {
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));
359         };
360 
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>
364         {
365             using forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>::operator();
366 
367 #       endif
368 
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.
371 
372 #       // Macros for the parameter's type modifiers.
373 #       if I & 0x000001
374 #         define PT0 T0 &
375 #       else
376 #         define PT0 T0 const &
377 #       endif
378 #       if I & 0x000002
379 #         define PT1 T1 &
380 #       else
381 #         define PT1 T1 const &
382 #       endif
383 #       if I & 0x000004
384 #         define PT2 T2 &
385 #       else
386 #         define PT2 T2 const &
387 #       endif
388 #       if I & 0x000008
389 #         define PT3 T3 &
390 #       else
391 #         define PT3 T3 const &
392 #       endif
393 #       if I & 0x000010
394 #         define PT4 T4 &
395 #       else
396 #         define PT4 T4 const &
397 #       endif
398 #       if I & 0x000020
399 #         define PT5 T5 &
400 #       else
401 #         define PT5 T5 const &
402 #       endif
403 #       if I & 0x000040
404 #         define PT6 T6 &
405 #       else
406 #         define PT6 T6 const &
407 #       endif
408 #       if I & 0x000080
409 #         define PT7 T7 &
410 #       else
411 #         define PT7 T7 const &
412 #       endif
413 #       if I & 0x000100
414 #         define PT8 T8 &
415 #       else
416 #         define PT8 T8 const &
417 #       endif
418 #       if I & 0x000200
419 #         define PT9 T9 &
420 #       else
421 #         define PT9 T9 const &
422 #       endif
423 #       if I & 0x000400
424 #         define PT10 T10 &
425 #       else
426 #         define PT10 T10 const &
427 #       endif
428 #       if I & 0x000800
429 #         define PT11 T11 &
430 #       else
431 #         define PT11 T11 const &
432 #       endif
433 #       if I & 0x001000
434 #         define PT12 T12 &
435 #       else
436 #         define PT12 T12 const &
437 #       endif
438 #       if I & 0x002000
439 #         define PT13 T13 &
440 #       else
441 #         define PT13 T13 const &
442 #       endif
443 #       if I & 0x004000
444 #         define PT14 T14 &
445 #       else
446 #         define PT14 T14 const &
447 #       endif
448 #       if I & 0x008000
449 #         define PT15 T15 &
450 #       else
451 #         define PT15 T15 const &
452 #       endif
453 
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))
457                 >::type
458             operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) const
459             {
460                 return static_cast<MD const* const>(this)
461                     ->target_function()(BOOST_PP_ENUM_PARAMS(N,a));
462             }
463             template< BOOST_PP_ENUM_PARAMS(N,typename T) >
464             inline typename boost::result_of<  F(BOOST_PP_ENUM_PARAMS(N,PT))
465                 >::type
466             operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a))
467             {
468                 return static_cast<MD* const>(this)
469                     ->target_function()(BOOST_PP_ENUM_PARAMS(N,a));
470             }
471 #       else
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_*
476 #       endif
477 
478 #       undef PT0
479 #       undef PT1
480 #       undef PT2
481 #       undef PT3
482 #       undef PT4
483 #       undef PT5
484 #       undef PT6
485 #       undef PT7
486 #       undef PT8
487 #       undef PT9
488 #       undef PT10
489 #       undef PT11
490 #       undef PT12
491 #       undef PT13
492 #       undef PT14
493 #       undef PT15
494 
495 #     endif // I < count
496 
497 #     undef I
498 #   endif // defined(BOOST_PP_IS_ITERATING)
499 
500 #endif // include guard
501 
502