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