]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | // 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> | |
165 | 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 | |
173 | operator()() const | |
174 | { | |
175 | return static_cast<MD const*>(this)->target_function()(); | |
176 | } | |
177 | ||
178 | inline typename boost::result_of< F() >::type | |
179 | 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 |