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