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: |
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 | |