]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Function library |
2 | ||
3 | // Copyright Douglas Gregor 2001-2006 | |
4 | // Copyright Emil Dotchevski 2007 | |
5 | // Use, modification and distribution is subject to the Boost Software License, Version 1.0. | |
6 | // (See accompanying file LICENSE_1_0.txt or copy at | |
7 | // http://www.boost.org/LICENSE_1_0.txt) | |
8 | ||
9 | // For more information, see http://www.boost.org | |
10 | ||
11 | // Note: this header is a header template and must NOT have multiple-inclusion | |
12 | // protection. | |
13 | #include <boost/function/detail/prologue.hpp> | |
14 | #include <boost/detail/no_exceptions_support.hpp> | |
15 | ||
16 | #if defined(BOOST_MSVC) | |
17 | # pragma warning( push ) | |
18 | # pragma warning( disable : 4127 ) // "conditional expression is constant" | |
19 | #endif | |
20 | ||
21 | #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) | |
22 | ||
23 | #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T) | |
24 | ||
25 | #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I) | |
26 | ||
27 | #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY) | |
28 | ||
29 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES | |
30 | # define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a) | |
31 | #else | |
32 | # include <boost/move/utility_core.hpp> | |
33 | # define BOOST_FUNCTION_ARG(J,I,D) ::boost::forward< BOOST_PP_CAT(T,I) >(BOOST_PP_CAT(a,I)) | |
34 | # define BOOST_FUNCTION_ARGS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG,BOOST_PP_EMPTY) | |
35 | #endif | |
36 | ||
37 | #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \ | |
38 | typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type); | |
39 | ||
40 | #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY) | |
41 | ||
42 | // Comma if nonzero number of arguments | |
43 | #if BOOST_FUNCTION_NUM_ARGS == 0 | |
44 | # define BOOST_FUNCTION_COMMA | |
45 | #else | |
46 | # define BOOST_FUNCTION_COMMA , | |
47 | #endif // BOOST_FUNCTION_NUM_ARGS > 0 | |
48 | ||
49 | // Class names used in this version of the code | |
50 | #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS) | |
51 | #define BOOST_FUNCTION_FUNCTION_INVOKER \ | |
52 | BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) | |
53 | #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ | |
54 | BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS) | |
55 | #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \ | |
56 | BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) | |
57 | #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \ | |
58 | BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) | |
59 | #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \ | |
60 | BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) | |
61 | #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \ | |
62 | BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) | |
63 | #define BOOST_FUNCTION_MEMBER_INVOKER \ | |
64 | BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS) | |
65 | #define BOOST_FUNCTION_VOID_MEMBER_INVOKER \ | |
66 | BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS) | |
67 | #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ | |
68 | BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) | |
69 | #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ | |
70 | BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) | |
71 | #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \ | |
72 | BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) | |
73 | #define BOOST_FUNCTION_GET_MEMBER_INVOKER \ | |
74 | BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS) | |
75 | #define BOOST_FUNCTION_GET_INVOKER \ | |
76 | BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS) | |
77 | #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS) | |
78 | ||
79 | #ifndef BOOST_NO_VOID_RETURNS | |
80 | # define BOOST_FUNCTION_VOID_RETURN_TYPE void | |
81 | # define BOOST_FUNCTION_RETURN(X) X | |
82 | #else | |
83 | # define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable | |
84 | # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE () | |
85 | #endif | |
86 | ||
87 | namespace boost { | |
88 | namespace detail { | |
89 | namespace function { | |
90 | template< | |
91 | typename FunctionPtr, | |
92 | typename R BOOST_FUNCTION_COMMA | |
93 | BOOST_FUNCTION_TEMPLATE_PARMS | |
94 | > | |
95 | struct BOOST_FUNCTION_FUNCTION_INVOKER | |
96 | { | |
97 | static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA | |
98 | BOOST_FUNCTION_PARMS) | |
99 | { | |
100 | FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr); | |
101 | return f(BOOST_FUNCTION_ARGS); | |
102 | } | |
103 | }; | |
104 | ||
105 | template< | |
106 | typename FunctionPtr, | |
107 | typename R BOOST_FUNCTION_COMMA | |
108 | BOOST_FUNCTION_TEMPLATE_PARMS | |
109 | > | |
110 | struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER | |
111 | { | |
112 | static BOOST_FUNCTION_VOID_RETURN_TYPE | |
113 | invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA | |
114 | BOOST_FUNCTION_PARMS) | |
115 | ||
116 | { | |
117 | FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr); | |
118 | BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS)); | |
119 | } | |
120 | }; | |
121 | ||
122 | template< | |
123 | typename FunctionObj, | |
124 | typename R BOOST_FUNCTION_COMMA | |
125 | BOOST_FUNCTION_TEMPLATE_PARMS | |
126 | > | |
127 | struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER | |
128 | { | |
129 | static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA | |
130 | BOOST_FUNCTION_PARMS) | |
131 | ||
132 | { | |
133 | FunctionObj* f; | |
134 | if (function_allows_small_object_optimization<FunctionObj>::value) | |
135 | f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data); | |
136 | else | |
137 | f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr); | |
138 | return (*f)(BOOST_FUNCTION_ARGS); | |
139 | } | |
140 | }; | |
141 | ||
142 | template< | |
143 | typename FunctionObj, | |
144 | typename R BOOST_FUNCTION_COMMA | |
145 | BOOST_FUNCTION_TEMPLATE_PARMS | |
146 | > | |
147 | struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER | |
148 | { | |
149 | static BOOST_FUNCTION_VOID_RETURN_TYPE | |
150 | invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA | |
151 | BOOST_FUNCTION_PARMS) | |
152 | ||
153 | { | |
154 | FunctionObj* f; | |
155 | if (function_allows_small_object_optimization<FunctionObj>::value) | |
156 | f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data); | |
157 | else | |
158 | f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr); | |
159 | BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); | |
160 | } | |
161 | }; | |
162 | ||
163 | template< | |
164 | typename FunctionObj, | |
165 | typename R BOOST_FUNCTION_COMMA | |
166 | BOOST_FUNCTION_TEMPLATE_PARMS | |
167 | > | |
168 | struct BOOST_FUNCTION_FUNCTION_REF_INVOKER | |
169 | { | |
170 | static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA | |
171 | BOOST_FUNCTION_PARMS) | |
172 | ||
173 | { | |
174 | FunctionObj* f = | |
175 | reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr); | |
176 | return (*f)(BOOST_FUNCTION_ARGS); | |
177 | } | |
178 | }; | |
179 | ||
180 | template< | |
181 | typename FunctionObj, | |
182 | typename R BOOST_FUNCTION_COMMA | |
183 | BOOST_FUNCTION_TEMPLATE_PARMS | |
184 | > | |
185 | struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER | |
186 | { | |
187 | static BOOST_FUNCTION_VOID_RETURN_TYPE | |
188 | invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA | |
189 | BOOST_FUNCTION_PARMS) | |
190 | ||
191 | { | |
192 | FunctionObj* f = | |
193 | reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr); | |
194 | BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); | |
195 | } | |
196 | }; | |
197 | ||
198 | #if BOOST_FUNCTION_NUM_ARGS > 0 | |
199 | /* Handle invocation of member pointers. */ | |
200 | template< | |
201 | typename MemberPtr, | |
202 | typename R BOOST_FUNCTION_COMMA | |
203 | BOOST_FUNCTION_TEMPLATE_PARMS | |
204 | > | |
205 | struct BOOST_FUNCTION_MEMBER_INVOKER | |
206 | { | |
207 | static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA | |
208 | BOOST_FUNCTION_PARMS) | |
209 | ||
210 | { | |
211 | MemberPtr* f = | |
212 | reinterpret_cast<MemberPtr*>(function_obj_ptr.data); | |
213 | return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS); | |
214 | } | |
215 | }; | |
216 | ||
217 | template< | |
218 | typename MemberPtr, | |
219 | typename R BOOST_FUNCTION_COMMA | |
220 | BOOST_FUNCTION_TEMPLATE_PARMS | |
221 | > | |
222 | struct BOOST_FUNCTION_VOID_MEMBER_INVOKER | |
223 | { | |
224 | static BOOST_FUNCTION_VOID_RETURN_TYPE | |
225 | invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA | |
226 | BOOST_FUNCTION_PARMS) | |
227 | ||
228 | { | |
229 | MemberPtr* f = | |
230 | reinterpret_cast<MemberPtr*>(function_obj_ptr.data); | |
231 | BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS)); | |
232 | } | |
233 | }; | |
234 | #endif | |
235 | ||
236 | template< | |
237 | typename FunctionPtr, | |
238 | typename R BOOST_FUNCTION_COMMA | |
239 | BOOST_FUNCTION_TEMPLATE_PARMS | |
240 | > | |
241 | struct BOOST_FUNCTION_GET_FUNCTION_INVOKER | |
242 | { | |
243 | typedef typename mpl::if_c<(is_void<R>::value), | |
244 | BOOST_FUNCTION_VOID_FUNCTION_INVOKER< | |
245 | FunctionPtr, | |
246 | R BOOST_FUNCTION_COMMA | |
247 | BOOST_FUNCTION_TEMPLATE_ARGS | |
248 | >, | |
249 | BOOST_FUNCTION_FUNCTION_INVOKER< | |
250 | FunctionPtr, | |
251 | R BOOST_FUNCTION_COMMA | |
252 | BOOST_FUNCTION_TEMPLATE_ARGS | |
253 | > | |
254 | >::type type; | |
255 | }; | |
256 | ||
257 | template< | |
258 | typename FunctionObj, | |
259 | typename R BOOST_FUNCTION_COMMA | |
260 | BOOST_FUNCTION_TEMPLATE_PARMS | |
261 | > | |
262 | struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER | |
263 | { | |
264 | typedef typename mpl::if_c<(is_void<R>::value), | |
265 | BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER< | |
266 | FunctionObj, | |
267 | R BOOST_FUNCTION_COMMA | |
268 | BOOST_FUNCTION_TEMPLATE_ARGS | |
269 | >, | |
270 | BOOST_FUNCTION_FUNCTION_OBJ_INVOKER< | |
271 | FunctionObj, | |
272 | R BOOST_FUNCTION_COMMA | |
273 | BOOST_FUNCTION_TEMPLATE_ARGS | |
274 | > | |
275 | >::type type; | |
276 | }; | |
277 | ||
278 | template< | |
279 | typename FunctionObj, | |
280 | typename R BOOST_FUNCTION_COMMA | |
281 | BOOST_FUNCTION_TEMPLATE_PARMS | |
282 | > | |
283 | struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER | |
284 | { | |
285 | typedef typename mpl::if_c<(is_void<R>::value), | |
286 | BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER< | |
287 | FunctionObj, | |
288 | R BOOST_FUNCTION_COMMA | |
289 | BOOST_FUNCTION_TEMPLATE_ARGS | |
290 | >, | |
291 | BOOST_FUNCTION_FUNCTION_REF_INVOKER< | |
292 | FunctionObj, | |
293 | R BOOST_FUNCTION_COMMA | |
294 | BOOST_FUNCTION_TEMPLATE_ARGS | |
295 | > | |
296 | >::type type; | |
297 | }; | |
298 | ||
299 | #if BOOST_FUNCTION_NUM_ARGS > 0 | |
300 | /* Retrieve the appropriate invoker for a member pointer. */ | |
301 | template< | |
302 | typename MemberPtr, | |
303 | typename R BOOST_FUNCTION_COMMA | |
304 | BOOST_FUNCTION_TEMPLATE_PARMS | |
305 | > | |
306 | struct BOOST_FUNCTION_GET_MEMBER_INVOKER | |
307 | { | |
308 | typedef typename mpl::if_c<(is_void<R>::value), | |
309 | BOOST_FUNCTION_VOID_MEMBER_INVOKER< | |
310 | MemberPtr, | |
311 | R BOOST_FUNCTION_COMMA | |
312 | BOOST_FUNCTION_TEMPLATE_ARGS | |
313 | >, | |
314 | BOOST_FUNCTION_MEMBER_INVOKER< | |
315 | MemberPtr, | |
316 | R BOOST_FUNCTION_COMMA | |
317 | BOOST_FUNCTION_TEMPLATE_ARGS | |
318 | > | |
319 | >::type type; | |
320 | }; | |
321 | #endif | |
322 | ||
323 | /* Given the tag returned by get_function_tag, retrieve the | |
324 | actual invoker that will be used for the given function | |
325 | object. | |
326 | ||
327 | Each specialization contains an "apply" nested class template | |
328 | that accepts the function object, return type, function | |
329 | argument types, and allocator. The resulting "apply" class | |
330 | contains two typedefs, "invoker_type" and "manager_type", | |
331 | which correspond to the invoker and manager types. */ | |
332 | template<typename Tag> | |
333 | struct BOOST_FUNCTION_GET_INVOKER { }; | |
334 | ||
335 | /* Retrieve the invoker for a function pointer. */ | |
336 | template<> | |
337 | struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag> | |
338 | { | |
339 | template<typename FunctionPtr, | |
340 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
341 | struct apply | |
342 | { | |
343 | typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< | |
344 | FunctionPtr, | |
345 | R BOOST_FUNCTION_COMMA | |
346 | BOOST_FUNCTION_TEMPLATE_ARGS | |
347 | >::type | |
348 | invoker_type; | |
349 | ||
350 | typedef functor_manager<FunctionPtr> manager_type; | |
351 | }; | |
352 | ||
353 | template<typename FunctionPtr, | |
354 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, | |
355 | typename Allocator> | |
356 | struct apply_a | |
357 | { | |
358 | typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< | |
359 | FunctionPtr, | |
360 | R BOOST_FUNCTION_COMMA | |
361 | BOOST_FUNCTION_TEMPLATE_ARGS | |
362 | >::type | |
363 | invoker_type; | |
364 | ||
365 | typedef functor_manager<FunctionPtr> manager_type; | |
366 | }; | |
367 | }; | |
368 | ||
369 | #if BOOST_FUNCTION_NUM_ARGS > 0 | |
370 | /* Retrieve the invoker for a member pointer. */ | |
371 | template<> | |
372 | struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag> | |
373 | { | |
374 | template<typename MemberPtr, | |
375 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
376 | struct apply | |
377 | { | |
378 | typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER< | |
379 | MemberPtr, | |
380 | R BOOST_FUNCTION_COMMA | |
381 | BOOST_FUNCTION_TEMPLATE_ARGS | |
382 | >::type | |
383 | invoker_type; | |
384 | ||
385 | typedef functor_manager<MemberPtr> manager_type; | |
386 | }; | |
387 | ||
388 | template<typename MemberPtr, | |
389 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, | |
390 | typename Allocator> | |
391 | struct apply_a | |
392 | { | |
393 | typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER< | |
394 | MemberPtr, | |
395 | R BOOST_FUNCTION_COMMA | |
396 | BOOST_FUNCTION_TEMPLATE_ARGS | |
397 | >::type | |
398 | invoker_type; | |
399 | ||
400 | typedef functor_manager<MemberPtr> manager_type; | |
401 | }; | |
402 | }; | |
403 | #endif | |
404 | ||
405 | /* Retrieve the invoker for a function object. */ | |
406 | template<> | |
407 | struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag> | |
408 | { | |
409 | template<typename FunctionObj, | |
410 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
411 | struct apply | |
412 | { | |
413 | typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< | |
414 | FunctionObj, | |
415 | R BOOST_FUNCTION_COMMA | |
416 | BOOST_FUNCTION_TEMPLATE_ARGS | |
417 | >::type | |
418 | invoker_type; | |
419 | ||
420 | typedef functor_manager<FunctionObj> manager_type; | |
421 | }; | |
422 | ||
423 | template<typename FunctionObj, | |
424 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, | |
425 | typename Allocator> | |
426 | struct apply_a | |
427 | { | |
428 | typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< | |
429 | FunctionObj, | |
430 | R BOOST_FUNCTION_COMMA | |
431 | BOOST_FUNCTION_TEMPLATE_ARGS | |
432 | >::type | |
433 | invoker_type; | |
434 | ||
435 | typedef functor_manager_a<FunctionObj, Allocator> manager_type; | |
436 | }; | |
437 | }; | |
438 | ||
439 | /* Retrieve the invoker for a reference to a function object. */ | |
440 | template<> | |
441 | struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag> | |
442 | { | |
443 | template<typename RefWrapper, | |
444 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
445 | struct apply | |
446 | { | |
447 | typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< | |
448 | typename RefWrapper::type, | |
449 | R BOOST_FUNCTION_COMMA | |
450 | BOOST_FUNCTION_TEMPLATE_ARGS | |
451 | >::type | |
452 | invoker_type; | |
453 | ||
454 | typedef reference_manager<typename RefWrapper::type> manager_type; | |
455 | }; | |
456 | ||
457 | template<typename RefWrapper, | |
458 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, | |
459 | typename Allocator> | |
460 | struct apply_a | |
461 | { | |
462 | typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< | |
463 | typename RefWrapper::type, | |
464 | R BOOST_FUNCTION_COMMA | |
465 | BOOST_FUNCTION_TEMPLATE_ARGS | |
466 | >::type | |
467 | invoker_type; | |
468 | ||
469 | typedef reference_manager<typename RefWrapper::type> manager_type; | |
470 | }; | |
471 | }; | |
472 | ||
473 | ||
474 | /** | |
475 | * vtable for a specific boost::function instance. This | |
476 | * structure must be an aggregate so that we can use static | |
477 | * initialization in boost::function's assign_to and assign_to_a | |
478 | * members. It therefore cannot have any constructors, | |
479 | * destructors, base classes, etc. | |
480 | */ | |
481 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
482 | struct BOOST_FUNCTION_VTABLE | |
483 | { | |
484 | #ifndef BOOST_NO_VOID_RETURNS | |
485 | typedef R result_type; | |
486 | #else | |
487 | typedef typename function_return_type<R>::type result_type; | |
488 | #endif // BOOST_NO_VOID_RETURNS | |
489 | ||
490 | typedef result_type (*invoker_type)(function_buffer& | |
491 | BOOST_FUNCTION_COMMA | |
492 | BOOST_FUNCTION_TEMPLATE_ARGS); | |
493 | ||
494 | template<typename F> | |
495 | bool assign_to(F f, function_buffer& functor) const | |
496 | { | |
497 | typedef typename get_function_tag<F>::type tag; | |
498 | return assign_to(f, functor, tag()); | |
499 | } | |
500 | template<typename F,typename Allocator> | |
501 | bool assign_to_a(F f, function_buffer& functor, Allocator a) const | |
502 | { | |
503 | typedef typename get_function_tag<F>::type tag; | |
504 | return assign_to_a(f, functor, a, tag()); | |
505 | } | |
506 | ||
507 | void clear(function_buffer& functor) const | |
508 | { | |
509 | if (base.manager) | |
510 | base.manager(functor, functor, destroy_functor_tag); | |
511 | } | |
512 | ||
513 | private: | |
514 | // Function pointers | |
515 | template<typename FunctionPtr> | |
516 | bool | |
517 | assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const | |
518 | { | |
519 | this->clear(functor); | |
520 | if (f) { | |
521 | // should be a reinterpret cast, but some compilers insist | |
522 | // on giving cv-qualifiers to free functions | |
523 | functor.members.func_ptr = reinterpret_cast<void (*)()>(f); | |
524 | return true; | |
525 | } else { | |
526 | return false; | |
527 | } | |
528 | } | |
529 | template<typename FunctionPtr,typename Allocator> | |
530 | bool | |
531 | assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const | |
532 | { | |
533 | return assign_to(f,functor,function_ptr_tag()); | |
534 | } | |
535 | ||
536 | // Member pointers | |
537 | #if BOOST_FUNCTION_NUM_ARGS > 0 | |
538 | template<typename MemberPtr> | |
539 | bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const | |
540 | { | |
541 | // DPG TBD: Add explicit support for member function | |
542 | // objects, so we invoke through mem_fn() but we retain the | |
543 | // right target_type() values. | |
544 | if (f) { | |
545 | this->assign_to(boost::mem_fn(f), functor); | |
546 | return true; | |
547 | } else { | |
548 | return false; | |
549 | } | |
550 | } | |
551 | template<typename MemberPtr,typename Allocator> | |
552 | bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const | |
553 | { | |
554 | // DPG TBD: Add explicit support for member function | |
555 | // objects, so we invoke through mem_fn() but we retain the | |
556 | // right target_type() values. | |
557 | if (f) { | |
558 | this->assign_to_a(boost::mem_fn(f), functor, a); | |
559 | return true; | |
560 | } else { | |
561 | return false; | |
562 | } | |
563 | } | |
564 | #endif // BOOST_FUNCTION_NUM_ARGS > 0 | |
565 | ||
566 | // Function objects | |
567 | // Assign to a function object using the small object optimization | |
568 | template<typename FunctionObj> | |
569 | void | |
570 | assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const | |
571 | { | |
572 | new (reinterpret_cast<void*>(functor.data)) FunctionObj(f); | |
573 | } | |
574 | template<typename FunctionObj,typename Allocator> | |
575 | void | |
576 | assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const | |
577 | { | |
578 | assign_functor(f,functor,mpl::true_()); | |
579 | } | |
580 | ||
581 | // Assign to a function object allocated on the heap. | |
582 | template<typename FunctionObj> | |
583 | void | |
584 | assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const | |
585 | { | |
586 | functor.members.obj_ptr = new FunctionObj(f); | |
587 | } | |
588 | template<typename FunctionObj,typename Allocator> | |
589 | void | |
590 | assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const | |
591 | { | |
592 | typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type; | |
593 | typedef typename Allocator::template rebind<functor_wrapper_type>::other | |
594 | wrapper_allocator_type; | |
595 | typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type; | |
596 | wrapper_allocator_type wrapper_allocator(a); | |
597 | wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); | |
598 | wrapper_allocator.construct(copy, functor_wrapper_type(f,a)); | |
599 | functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); | |
600 | functor.members.obj_ptr = new_f; | |
601 | } | |
602 | ||
603 | template<typename FunctionObj> | |
604 | bool | |
605 | assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const | |
606 | { | |
607 | if (!boost::detail::function::has_empty_target(boost::addressof(f))) { | |
608 | assign_functor(f, functor, | |
609 | mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>()); | |
610 | return true; | |
611 | } else { | |
612 | return false; | |
613 | } | |
614 | } | |
615 | template<typename FunctionObj,typename Allocator> | |
616 | bool | |
617 | assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const | |
618 | { | |
619 | if (!boost::detail::function::has_empty_target(boost::addressof(f))) { | |
620 | assign_functor_a(f, functor, a, | |
621 | mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>()); | |
622 | return true; | |
623 | } else { | |
624 | return false; | |
625 | } | |
626 | } | |
627 | ||
628 | // Reference to a function object | |
629 | template<typename FunctionObj> | |
630 | bool | |
631 | assign_to(const reference_wrapper<FunctionObj>& f, | |
632 | function_buffer& functor, function_obj_ref_tag) const | |
633 | { | |
634 | functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer()); | |
635 | functor.members.obj_ref.is_const_qualified = is_const<FunctionObj>::value; | |
636 | functor.members.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value; | |
637 | return true; | |
638 | } | |
639 | template<typename FunctionObj,typename Allocator> | |
640 | bool | |
641 | assign_to_a(const reference_wrapper<FunctionObj>& f, | |
642 | function_buffer& functor, Allocator, function_obj_ref_tag) const | |
643 | { | |
644 | return assign_to(f,functor,function_obj_ref_tag()); | |
645 | } | |
646 | ||
647 | public: | |
648 | vtable_base base; | |
649 | invoker_type invoker; | |
650 | }; | |
651 | } // end namespace function | |
652 | } // end namespace detail | |
653 | ||
654 | template< | |
655 | typename R BOOST_FUNCTION_COMMA | |
656 | BOOST_FUNCTION_TEMPLATE_PARMS | |
657 | > | |
658 | class BOOST_FUNCTION_FUNCTION : public function_base | |
659 | ||
660 | #if BOOST_FUNCTION_NUM_ARGS == 1 | |
661 | ||
662 | , public std::unary_function<T0,R> | |
663 | ||
664 | #elif BOOST_FUNCTION_NUM_ARGS == 2 | |
665 | ||
666 | , public std::binary_function<T0,T1,R> | |
667 | ||
668 | #endif | |
669 | ||
670 | { | |
671 | public: | |
672 | #ifndef BOOST_NO_VOID_RETURNS | |
673 | typedef R result_type; | |
674 | #else | |
675 | typedef typename boost::detail::function::function_return_type<R>::type | |
676 | result_type; | |
677 | #endif // BOOST_NO_VOID_RETURNS | |
678 | ||
679 | private: | |
680 | typedef boost::detail::function::BOOST_FUNCTION_VTABLE< | |
681 | R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> | |
682 | vtable_type; | |
683 | ||
684 | vtable_type* get_vtable() const { | |
685 | return reinterpret_cast<vtable_type*>( | |
686 | reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01)); | |
687 | } | |
688 | ||
689 | struct clear_type {}; | |
690 | ||
691 | public: | |
692 | BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); | |
693 | ||
694 | // add signature for boost::lambda | |
695 | template<typename Args> | |
696 | struct sig | |
697 | { | |
698 | typedef result_type type; | |
699 | }; | |
700 | ||
701 | #if BOOST_FUNCTION_NUM_ARGS == 1 | |
702 | typedef T0 argument_type; | |
703 | #elif BOOST_FUNCTION_NUM_ARGS == 2 | |
704 | typedef T0 first_argument_type; | |
705 | typedef T1 second_argument_type; | |
706 | #endif | |
707 | ||
708 | BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS); | |
709 | BOOST_FUNCTION_ARG_TYPES | |
710 | ||
711 | typedef BOOST_FUNCTION_FUNCTION self_type; | |
712 | ||
713 | BOOST_FUNCTION_FUNCTION() : function_base() { } | |
714 | ||
715 | // MSVC chokes if the following two constructors are collapsed into | |
716 | // one with a default parameter. | |
717 | template<typename Functor> | |
718 | BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f | |
719 | #ifndef BOOST_NO_SFINAE | |
720 | ,typename boost::enable_if_c< | |
721 | !(is_integral<Functor>::value), | |
722 | int>::type = 0 | |
723 | #endif // BOOST_NO_SFINAE | |
724 | ) : | |
725 | function_base() | |
726 | { | |
727 | this->assign_to(f); | |
728 | } | |
729 | template<typename Functor,typename Allocator> | |
730 | BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a | |
731 | #ifndef BOOST_NO_SFINAE | |
732 | ,typename boost::enable_if_c< | |
733 | !(is_integral<Functor>::value), | |
734 | int>::type = 0 | |
735 | #endif // BOOST_NO_SFINAE | |
736 | ) : | |
737 | function_base() | |
738 | { | |
739 | this->assign_to_a(f,a); | |
740 | } | |
741 | ||
742 | #ifndef BOOST_NO_SFINAE | |
743 | BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { } | |
744 | #else | |
745 | BOOST_FUNCTION_FUNCTION(int zero) : function_base() | |
746 | { | |
747 | BOOST_ASSERT(zero == 0); | |
748 | } | |
749 | #endif | |
750 | ||
751 | BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base() | |
752 | { | |
753 | this->assign_to_own(f); | |
754 | } | |
755 | ||
756 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
757 | BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base() | |
758 | { | |
759 | this->move_assign(f); | |
760 | } | |
761 | #endif | |
762 | ||
763 | ~BOOST_FUNCTION_FUNCTION() { clear(); } | |
764 | ||
765 | result_type operator()(BOOST_FUNCTION_PARMS) const | |
766 | { | |
767 | if (this->empty()) | |
768 | boost::throw_exception(bad_function_call()); | |
769 | ||
770 | return get_vtable()->invoker | |
771 | (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); | |
772 | } | |
773 | ||
774 | // The distinction between when to use BOOST_FUNCTION_FUNCTION and | |
775 | // when to use self_type is obnoxious. MSVC cannot handle self_type as | |
776 | // the return type of these assignment operators, but Borland C++ cannot | |
777 | // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to | |
778 | // construct. | |
779 | template<typename Functor> | |
780 | #ifndef BOOST_NO_SFINAE | |
781 | typename boost::enable_if_c< | |
782 | !(is_integral<Functor>::value), | |
783 | BOOST_FUNCTION_FUNCTION&>::type | |
784 | #else | |
785 | BOOST_FUNCTION_FUNCTION& | |
786 | #endif | |
787 | operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) | |
788 | { | |
789 | this->clear(); | |
790 | BOOST_TRY { | |
791 | this->assign_to(f); | |
792 | } BOOST_CATCH (...) { | |
793 | vtable = 0; | |
794 | BOOST_RETHROW; | |
795 | } | |
796 | BOOST_CATCH_END | |
797 | return *this; | |
798 | } | |
799 | template<typename Functor,typename Allocator> | |
800 | void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a) | |
801 | { | |
802 | this->clear(); | |
803 | BOOST_TRY{ | |
804 | this->assign_to_a(f,a); | |
805 | } BOOST_CATCH (...) { | |
806 | vtable = 0; | |
807 | BOOST_RETHROW; | |
808 | } | |
809 | BOOST_CATCH_END | |
810 | } | |
811 | ||
812 | #ifndef BOOST_NO_SFINAE | |
813 | BOOST_FUNCTION_FUNCTION& operator=(clear_type*) | |
814 | { | |
815 | this->clear(); | |
816 | return *this; | |
817 | } | |
818 | #else | |
819 | BOOST_FUNCTION_FUNCTION& operator=(int zero) | |
820 | { | |
821 | BOOST_ASSERT(zero == 0); | |
822 | this->clear(); | |
823 | return *this; | |
824 | } | |
825 | #endif | |
826 | ||
827 | // Assignment from another BOOST_FUNCTION_FUNCTION | |
828 | BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) | |
829 | { | |
830 | if (&f == this) | |
831 | return *this; | |
832 | ||
833 | this->clear(); | |
834 | BOOST_TRY { | |
835 | this->assign_to_own(f); | |
836 | } BOOST_CATCH (...) { | |
837 | vtable = 0; | |
838 | BOOST_RETHROW; | |
839 | } | |
840 | BOOST_CATCH_END | |
841 | return *this; | |
842 | } | |
843 | ||
844 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
845 | // Move assignment from another BOOST_FUNCTION_FUNCTION | |
846 | BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f) | |
847 | { | |
848 | if (&f == this) | |
849 | return *this; | |
850 | ||
851 | this->clear(); | |
852 | BOOST_TRY { | |
853 | this->move_assign(f); | |
854 | } BOOST_CATCH (...) { | |
855 | vtable = 0; | |
856 | BOOST_RETHROW; | |
857 | } | |
858 | BOOST_CATCH_END | |
859 | return *this; | |
860 | } | |
861 | #endif | |
862 | ||
863 | void swap(BOOST_FUNCTION_FUNCTION& other) | |
864 | { | |
865 | if (&other == this) | |
866 | return; | |
867 | ||
868 | BOOST_FUNCTION_FUNCTION tmp; | |
869 | tmp.move_assign(*this); | |
870 | this->move_assign(other); | |
871 | other.move_assign(tmp); | |
872 | } | |
873 | ||
874 | // Clear out a target, if there is one | |
875 | void clear() | |
876 | { | |
877 | if (vtable) { | |
878 | if (!this->has_trivial_copy_and_destroy()) | |
879 | get_vtable()->clear(this->functor); | |
880 | vtable = 0; | |
881 | } | |
882 | } | |
883 | ||
884 | #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG) | |
885 | // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it | |
886 | operator bool () const { return !this->empty(); } | |
887 | #else | |
888 | private: | |
889 | struct dummy { | |
890 | void nonnull() {} | |
891 | }; | |
892 | ||
893 | typedef void (dummy::*safe_bool)(); | |
894 | ||
895 | public: | |
896 | operator safe_bool () const | |
897 | { return (this->empty())? 0 : &dummy::nonnull; } | |
898 | ||
899 | bool operator!() const | |
900 | { return this->empty(); } | |
901 | #endif | |
902 | ||
903 | private: | |
904 | void assign_to_own(const BOOST_FUNCTION_FUNCTION& f) | |
905 | { | |
906 | if (!f.empty()) { | |
907 | this->vtable = f.vtable; | |
908 | if (this->has_trivial_copy_and_destroy()) | |
909 | this->functor = f.functor; | |
910 | else | |
911 | get_vtable()->base.manager(f.functor, this->functor, | |
912 | boost::detail::function::clone_functor_tag); | |
913 | } | |
914 | } | |
915 | ||
916 | template<typename Functor> | |
917 | void assign_to(Functor f) | |
918 | { | |
919 | using boost::detail::function::vtable_base; | |
920 | ||
921 | typedef typename boost::detail::function::get_function_tag<Functor>::type tag; | |
922 | typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; | |
923 | typedef typename get_invoker:: | |
924 | template apply<Functor, R BOOST_FUNCTION_COMMA | |
925 | BOOST_FUNCTION_TEMPLATE_ARGS> | |
926 | handler_type; | |
927 | ||
928 | typedef typename handler_type::invoker_type invoker_type; | |
929 | typedef typename handler_type::manager_type manager_type; | |
930 | ||
931 | // Note: it is extremely important that this initialization use | |
932 | // static initialization. Otherwise, we will have a race | |
933 | // condition here in multi-threaded code. See | |
934 | // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/. | |
935 | static const vtable_type stored_vtable = | |
936 | { { &manager_type::manage }, &invoker_type::invoke }; | |
937 | ||
938 | if (stored_vtable.assign_to(f, functor)) { | |
939 | std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base); | |
940 | // coverity[pointless_expression]: suppress coverity warnings on apparant if(const). | |
941 | if (boost::has_trivial_copy_constructor<Functor>::value && | |
942 | boost::has_trivial_destructor<Functor>::value && | |
943 | boost::detail::function::function_allows_small_object_optimization<Functor>::value) | |
944 | value |= static_cast<std::size_t>(0x01); | |
945 | vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value); | |
946 | } else | |
947 | vtable = 0; | |
948 | } | |
949 | ||
950 | template<typename Functor,typename Allocator> | |
951 | void assign_to_a(Functor f,Allocator a) | |
952 | { | |
953 | using boost::detail::function::vtable_base; | |
954 | ||
955 | typedef typename boost::detail::function::get_function_tag<Functor>::type tag; | |
956 | typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; | |
957 | typedef typename get_invoker:: | |
958 | template apply_a<Functor, R BOOST_FUNCTION_COMMA | |
959 | BOOST_FUNCTION_TEMPLATE_ARGS, | |
960 | Allocator> | |
961 | handler_type; | |
962 | ||
963 | typedef typename handler_type::invoker_type invoker_type; | |
964 | typedef typename handler_type::manager_type manager_type; | |
965 | ||
966 | // Note: it is extremely important that this initialization use | |
967 | // static initialization. Otherwise, we will have a race | |
968 | // condition here in multi-threaded code. See | |
969 | // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/. | |
970 | static const vtable_type stored_vtable = | |
971 | { { &manager_type::manage }, &invoker_type::invoke }; | |
972 | ||
973 | if (stored_vtable.assign_to_a(f, functor, a)) { | |
974 | std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base); | |
975 | // coverity[pointless_expression]: suppress coverity warnings on apparant if(const). | |
976 | if (boost::has_trivial_copy_constructor<Functor>::value && | |
977 | boost::has_trivial_destructor<Functor>::value && | |
978 | boost::detail::function::function_allows_small_object_optimization<Functor>::value) | |
979 | value |= static_cast<std::size_t>(0x01); | |
980 | vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value); | |
981 | } else | |
982 | vtable = 0; | |
983 | } | |
984 | ||
985 | // Moves the value from the specified argument to *this. If the argument | |
986 | // has its function object allocated on the heap, move_assign will pass | |
987 | // its buffer to *this, and set the argument's buffer pointer to NULL. | |
988 | void move_assign(BOOST_FUNCTION_FUNCTION& f) | |
989 | { | |
990 | if (&f == this) | |
991 | return; | |
992 | ||
993 | BOOST_TRY { | |
994 | if (!f.empty()) { | |
995 | this->vtable = f.vtable; | |
996 | if (this->has_trivial_copy_and_destroy()) | |
997 | this->functor = f.functor; | |
998 | else | |
999 | get_vtable()->base.manager(f.functor, this->functor, | |
1000 | boost::detail::function::move_functor_tag); | |
1001 | f.vtable = 0; | |
1002 | } else { | |
1003 | clear(); | |
1004 | } | |
1005 | } BOOST_CATCH (...) { | |
1006 | vtable = 0; | |
1007 | BOOST_RETHROW; | |
1008 | } | |
1009 | BOOST_CATCH_END | |
1010 | } | |
1011 | }; | |
1012 | ||
1013 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
1014 | inline void swap(BOOST_FUNCTION_FUNCTION< | |
1015 | R BOOST_FUNCTION_COMMA | |
1016 | BOOST_FUNCTION_TEMPLATE_ARGS | |
1017 | >& f1, | |
1018 | BOOST_FUNCTION_FUNCTION< | |
1019 | R BOOST_FUNCTION_COMMA | |
1020 | BOOST_FUNCTION_TEMPLATE_ARGS | |
1021 | >& f2) | |
1022 | { | |
1023 | f1.swap(f2); | |
1024 | } | |
1025 | ||
1026 | // Poison comparisons between boost::function objects of the same type. | |
1027 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
1028 | void operator==(const BOOST_FUNCTION_FUNCTION< | |
1029 | R BOOST_FUNCTION_COMMA | |
1030 | BOOST_FUNCTION_TEMPLATE_ARGS>&, | |
1031 | const BOOST_FUNCTION_FUNCTION< | |
1032 | R BOOST_FUNCTION_COMMA | |
1033 | BOOST_FUNCTION_TEMPLATE_ARGS>&); | |
1034 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
1035 | void operator!=(const BOOST_FUNCTION_FUNCTION< | |
1036 | R BOOST_FUNCTION_COMMA | |
1037 | BOOST_FUNCTION_TEMPLATE_ARGS>&, | |
1038 | const BOOST_FUNCTION_FUNCTION< | |
1039 | R BOOST_FUNCTION_COMMA | |
1040 | BOOST_FUNCTION_TEMPLATE_ARGS>& ); | |
1041 | ||
1042 | #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) | |
1043 | ||
1044 | #if BOOST_FUNCTION_NUM_ARGS == 0 | |
1045 | #define BOOST_FUNCTION_PARTIAL_SPEC R (void) | |
1046 | #else | |
1047 | #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)) | |
1048 | #endif | |
1049 | ||
1050 | template<typename R BOOST_FUNCTION_COMMA | |
1051 | BOOST_FUNCTION_TEMPLATE_PARMS> | |
1052 | class function<BOOST_FUNCTION_PARTIAL_SPEC> | |
1053 | : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> | |
1054 | { | |
1055 | typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type; | |
1056 | typedef function self_type; | |
1057 | ||
1058 | struct clear_type {}; | |
1059 | ||
1060 | public: | |
1061 | ||
1062 | function() : base_type() {} | |
1063 | ||
1064 | template<typename Functor> | |
1065 | function(Functor f | |
1066 | #ifndef BOOST_NO_SFINAE | |
1067 | ,typename boost::enable_if_c< | |
1068 | !(is_integral<Functor>::value), | |
1069 | int>::type = 0 | |
1070 | #endif | |
1071 | ) : | |
1072 | base_type(f) | |
1073 | { | |
1074 | } | |
1075 | template<typename Functor,typename Allocator> | |
1076 | function(Functor f, Allocator a | |
1077 | #ifndef BOOST_NO_SFINAE | |
1078 | ,typename boost::enable_if_c< | |
1079 | !(is_integral<Functor>::value), | |
1080 | int>::type = 0 | |
1081 | #endif | |
1082 | ) : | |
1083 | base_type(f,a) | |
1084 | { | |
1085 | } | |
1086 | ||
1087 | #ifndef BOOST_NO_SFINAE | |
1088 | function(clear_type*) : base_type() {} | |
1089 | #endif | |
1090 | ||
1091 | function(const self_type& f) : base_type(static_cast<const base_type&>(f)){} | |
1092 | ||
1093 | function(const base_type& f) : base_type(static_cast<const base_type&>(f)){} | |
1094 | ||
1095 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
1096 | // Move constructors | |
1097 | function(self_type&& f): base_type(static_cast<base_type&&>(f)){} | |
1098 | function(base_type&& f): base_type(static_cast<base_type&&>(f)){} | |
1099 | #endif | |
1100 | ||
1101 | self_type& operator=(const self_type& f) | |
1102 | { | |
1103 | self_type(f).swap(*this); | |
1104 | return *this; | |
1105 | } | |
1106 | ||
1107 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
1108 | self_type& operator=(self_type&& f) | |
1109 | { | |
1110 | self_type(static_cast<self_type&&>(f)).swap(*this); | |
1111 | return *this; | |
1112 | } | |
1113 | #endif | |
1114 | ||
1115 | template<typename Functor> | |
1116 | #ifndef BOOST_NO_SFINAE | |
1117 | typename boost::enable_if_c< | |
1118 | !(is_integral<Functor>::value), | |
1119 | self_type&>::type | |
1120 | #else | |
1121 | self_type& | |
1122 | #endif | |
1123 | operator=(Functor f) | |
1124 | { | |
1125 | self_type(f).swap(*this); | |
1126 | return *this; | |
1127 | } | |
1128 | ||
1129 | #ifndef BOOST_NO_SFINAE | |
1130 | self_type& operator=(clear_type*) | |
1131 | { | |
1132 | this->clear(); | |
1133 | return *this; | |
1134 | } | |
1135 | #endif | |
1136 | ||
1137 | self_type& operator=(const base_type& f) | |
1138 | { | |
1139 | self_type(f).swap(*this); | |
1140 | return *this; | |
1141 | } | |
1142 | ||
1143 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
1144 | self_type& operator=(base_type&& f) | |
1145 | { | |
1146 | self_type(static_cast<base_type&&>(f)).swap(*this); | |
1147 | return *this; | |
1148 | } | |
1149 | #endif | |
1150 | }; | |
1151 | ||
1152 | #undef BOOST_FUNCTION_PARTIAL_SPEC | |
1153 | #endif // have partial specialization | |
1154 | ||
1155 | } // end namespace boost | |
1156 | ||
1157 | // Cleanup after ourselves... | |
1158 | #undef BOOST_FUNCTION_VTABLE | |
1159 | #undef BOOST_FUNCTION_COMMA | |
1160 | #undef BOOST_FUNCTION_FUNCTION | |
1161 | #undef BOOST_FUNCTION_FUNCTION_INVOKER | |
1162 | #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER | |
1163 | #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER | |
1164 | #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER | |
1165 | #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER | |
1166 | #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER | |
1167 | #undef BOOST_FUNCTION_MEMBER_INVOKER | |
1168 | #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER | |
1169 | #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER | |
1170 | #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER | |
1171 | #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER | |
1172 | #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER | |
1173 | #undef BOOST_FUNCTION_GET_INVOKER | |
1174 | #undef BOOST_FUNCTION_TEMPLATE_PARMS | |
1175 | #undef BOOST_FUNCTION_TEMPLATE_ARGS | |
1176 | #undef BOOST_FUNCTION_PARMS | |
1177 | #undef BOOST_FUNCTION_PARM | |
1178 | #ifdef BOOST_FUNCTION_ARG | |
1179 | # undef BOOST_FUNCTION_ARG | |
1180 | #endif | |
1181 | #undef BOOST_FUNCTION_ARGS | |
1182 | #undef BOOST_FUNCTION_ARG_TYPE | |
1183 | #undef BOOST_FUNCTION_ARG_TYPES | |
1184 | #undef BOOST_FUNCTION_VOID_RETURN_TYPE | |
1185 | #undef BOOST_FUNCTION_RETURN | |
1186 | ||
1187 | #if defined(BOOST_MSVC) | |
1188 | # pragma warning( pop ) | |
1189 | #endif |