]>
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> | |
92f5a8d4 | 14 | #include <boost/core/no_exceptions_support.hpp> |
7c673cae FG |
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 | |
92f5a8d4 | 32 | # define BOOST_FUNCTION_ARG(J,I,D) static_cast<BOOST_PP_CAT(T,I)&&>(BOOST_PP_CAT(a,I)) |
7c673cae FG |
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 | { | |
92f5a8d4 | 242 | typedef typename conditional<(is_void<R>::value), |
7c673cae FG |
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 | { | |
92f5a8d4 | 263 | typedef typename conditional<(is_void<R>::value), |
7c673cae FG |
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 | { | |
92f5a8d4 | 284 | typedef typename conditional<(is_void<R>::value), |
7c673cae FG |
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 | { | |
92f5a8d4 | 307 | typedef typename conditional<(is_void<R>::value), |
7c673cae FG |
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 | ||
92f5a8d4 TL |
352 | template<typename FunctionPtr, typename Allocator, |
353 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
7c673cae FG |
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 | ||
92f5a8d4 TL |
386 | template<typename MemberPtr, typename Allocator, |
387 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
7c673cae FG |
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 | ||
92f5a8d4 TL |
420 | template<typename FunctionObj, typename Allocator, |
421 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
7c673cae FG |
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 | ||
92f5a8d4 TL |
453 | template<typename RefWrapper, typename Allocator, |
454 | typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
7c673cae FG |
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 | |
92f5a8d4 | 565 | assign_functor(FunctionObj f, function_buffer& functor, true_type) const |
7c673cae FG |
566 | { |
567 | new (reinterpret_cast<void*>(functor.data)) FunctionObj(f); | |
568 | } | |
569 | template<typename FunctionObj,typename Allocator> | |
570 | void | |
92f5a8d4 | 571 | assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, true_type) const |
7c673cae | 572 | { |
92f5a8d4 | 573 | assign_functor(f,functor,true_type()); |
7c673cae FG |
574 | } |
575 | ||
576 | // Assign to a function object allocated on the heap. | |
577 | template<typename FunctionObj> | |
578 | void | |
92f5a8d4 | 579 | assign_functor(FunctionObj f, function_buffer& functor, false_type) const |
7c673cae FG |
580 | { |
581 | functor.members.obj_ptr = new FunctionObj(f); | |
582 | } | |
583 | template<typename FunctionObj,typename Allocator> | |
584 | void | |
92f5a8d4 | 585 | assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, false_type) const |
7c673cae FG |
586 | { |
587 | typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type; | |
11fdf7f2 | 588 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
7c673cae FG |
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; | |
11fdf7f2 TL |
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 | |
7c673cae FG |
596 | wrapper_allocator_type wrapper_allocator(a); |
597 | wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); | |
11fdf7f2 | 598 | #if defined(BOOST_NO_CXX11_ALLOCATOR) |
7c673cae | 599 | wrapper_allocator.construct(copy, functor_wrapper_type(f,a)); |
11fdf7f2 TL |
600 | #else |
601 | std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, functor_wrapper_type(f,a)); | |
602 | #endif | |
7c673cae FG |
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, | |
92f5a8d4 | 613 | integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>()); |
7c673cae FG |
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, | |
92f5a8d4 | 625 | integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>()); |
7c673cae FG |
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 | |
7c673cae FG |
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 | ||
92f5a8d4 | 706 | BOOST_DEFAULTED_FUNCTION(BOOST_FUNCTION_FUNCTION(), : function_base() {}) |
7c673cae FG |
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 | |
92f5a8d4 | 713 | ,typename boost::enable_if_< |
7c673cae FG |
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 | |
92f5a8d4 | 725 | ,typename boost::enable_if_< |
7c673cae FG |
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(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 | |
92f5a8d4 | 774 | typename boost::enable_if_< |
7c673cae FG |
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; | |
f67539c2 | 901 | if (this->has_trivial_copy_and_destroy()) { |
92f5a8d4 TL |
902 | // Don't operate on storage directly since union type doesn't relax |
903 | // strict aliasing rules, despite of having member char type. | |
f67539c2 TL |
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 | |
92f5a8d4 | 910 | std::memcpy(this->functor.data, f.functor.data, sizeof(boost::detail::function::function_buffer)); |
f67539c2 TL |
911 | # if defined(BOOST_GCC) && (BOOST_GCC >= 40700) |
912 | # pragma GCC diagnostic pop | |
913 | # endif | |
914 | } else | |
7c673cae FG |
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:: | |
92f5a8d4 TL |
962 | template apply_a<Functor, Allocator, R BOOST_FUNCTION_COMMA |
963 | BOOST_FUNCTION_TEMPLATE_ARGS> | |
7c673cae FG |
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; | |
f67539c2 | 999 | if (this->has_trivial_copy_and_destroy()) { |
92f5a8d4 TL |
1000 | // Don't operate on storage directly since union type doesn't relax |
1001 | // strict aliasing rules, despite of having member char type. | |
f67539c2 TL |
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 | |
92f5a8d4 | 1008 | std::memcpy(this->functor.data, f.functor.data, sizeof(this->functor.data)); |
f67539c2 TL |
1009 | # if defined(BOOST_GCC) && (BOOST_GCC >= 40700) |
1010 | # pragma GCC diagnostic pop | |
1011 | # endif | |
1012 | } else | |
1e59de90 TL |
1013 | #if defined(BOOST_GCC) && (__GNUC__ == 11) |
1014 | # pragma GCC diagnostic push | |
1015 | // False positive in GCC 11 for empty function objects (function_n_test.cpp:673) | |
1016 | # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" | |
1017 | #endif | |
7c673cae FG |
1018 | get_vtable()->base.manager(f.functor, this->functor, |
1019 | boost::detail::function::move_functor_tag); | |
1e59de90 TL |
1020 | #if defined(BOOST_GCC) && (__GNUC__ == 11) |
1021 | # pragma GCC diagnostic pop | |
1022 | #endif | |
7c673cae FG |
1023 | f.vtable = 0; |
1024 | } else { | |
1025 | clear(); | |
1026 | } | |
1027 | } BOOST_CATCH (...) { | |
1028 | vtable = 0; | |
1029 | BOOST_RETHROW; | |
1030 | } | |
1031 | BOOST_CATCH_END | |
1032 | } | |
1033 | }; | |
1034 | ||
1035 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
1036 | inline void swap(BOOST_FUNCTION_FUNCTION< | |
1037 | R BOOST_FUNCTION_COMMA | |
1038 | BOOST_FUNCTION_TEMPLATE_ARGS | |
1039 | >& f1, | |
1040 | BOOST_FUNCTION_FUNCTION< | |
1041 | R BOOST_FUNCTION_COMMA | |
1042 | BOOST_FUNCTION_TEMPLATE_ARGS | |
1043 | >& f2) | |
1044 | { | |
1045 | f1.swap(f2); | |
1046 | } | |
1047 | ||
1048 | // Poison comparisons between boost::function objects of the same type. | |
1049 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
1050 | void operator==(const BOOST_FUNCTION_FUNCTION< | |
1051 | R BOOST_FUNCTION_COMMA | |
1052 | BOOST_FUNCTION_TEMPLATE_ARGS>&, | |
1053 | const BOOST_FUNCTION_FUNCTION< | |
1054 | R BOOST_FUNCTION_COMMA | |
1055 | BOOST_FUNCTION_TEMPLATE_ARGS>&); | |
1056 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> | |
1057 | void operator!=(const BOOST_FUNCTION_FUNCTION< | |
1058 | R BOOST_FUNCTION_COMMA | |
1059 | BOOST_FUNCTION_TEMPLATE_ARGS>&, | |
1060 | const BOOST_FUNCTION_FUNCTION< | |
1061 | R BOOST_FUNCTION_COMMA | |
1062 | BOOST_FUNCTION_TEMPLATE_ARGS>& ); | |
1063 | ||
1064 | #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) | |
1065 | ||
1066 | #if BOOST_FUNCTION_NUM_ARGS == 0 | |
1067 | #define BOOST_FUNCTION_PARTIAL_SPEC R (void) | |
1068 | #else | |
92f5a8d4 | 1069 | #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_FUNCTION_TEMPLATE_ARGS) |
7c673cae FG |
1070 | #endif |
1071 | ||
1072 | template<typename R BOOST_FUNCTION_COMMA | |
1073 | BOOST_FUNCTION_TEMPLATE_PARMS> | |
1074 | class function<BOOST_FUNCTION_PARTIAL_SPEC> | |
1075 | : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> | |
1076 | { | |
1077 | typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type; | |
1078 | typedef function self_type; | |
1079 | ||
1080 | struct clear_type {}; | |
1081 | ||
1082 | public: | |
1083 | ||
92f5a8d4 | 1084 | BOOST_DEFAULTED_FUNCTION(function(), : base_type() {}) |
7c673cae FG |
1085 | |
1086 | template<typename Functor> | |
1087 | function(Functor f | |
1088 | #ifndef BOOST_NO_SFINAE | |
92f5a8d4 | 1089 | ,typename boost::enable_if_< |
7c673cae FG |
1090 | !(is_integral<Functor>::value), |
1091 | int>::type = 0 | |
1092 | #endif | |
1093 | ) : | |
1094 | base_type(f) | |
1095 | { | |
1096 | } | |
1097 | template<typename Functor,typename Allocator> | |
1098 | function(Functor f, Allocator a | |
1099 | #ifndef BOOST_NO_SFINAE | |
92f5a8d4 | 1100 | ,typename boost::enable_if_< |
7c673cae FG |
1101 | !(is_integral<Functor>::value), |
1102 | int>::type = 0 | |
1103 | #endif | |
1104 | ) : | |
1105 | base_type(f,a) | |
1106 | { | |
1107 | } | |
1108 | ||
1109 | #ifndef BOOST_NO_SFINAE | |
1110 | function(clear_type*) : base_type() {} | |
1111 | #endif | |
1112 | ||
1113 | function(const self_type& f) : base_type(static_cast<const base_type&>(f)){} | |
1114 | ||
1115 | function(const base_type& f) : base_type(static_cast<const base_type&>(f)){} | |
1116 | ||
1117 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
1118 | // Move constructors | |
1119 | function(self_type&& f): base_type(static_cast<base_type&&>(f)){} | |
1120 | function(base_type&& f): base_type(static_cast<base_type&&>(f)){} | |
1121 | #endif | |
1122 | ||
1123 | self_type& operator=(const self_type& f) | |
1124 | { | |
1125 | self_type(f).swap(*this); | |
1126 | return *this; | |
1127 | } | |
1128 | ||
1129 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
1130 | self_type& operator=(self_type&& f) | |
1131 | { | |
1132 | self_type(static_cast<self_type&&>(f)).swap(*this); | |
1133 | return *this; | |
1134 | } | |
1135 | #endif | |
1136 | ||
1137 | template<typename Functor> | |
1138 | #ifndef BOOST_NO_SFINAE | |
92f5a8d4 | 1139 | typename boost::enable_if_< |
7c673cae FG |
1140 | !(is_integral<Functor>::value), |
1141 | self_type&>::type | |
1142 | #else | |
1143 | self_type& | |
1144 | #endif | |
1145 | operator=(Functor f) | |
1146 | { | |
1147 | self_type(f).swap(*this); | |
1148 | return *this; | |
1149 | } | |
1150 | ||
1151 | #ifndef BOOST_NO_SFINAE | |
1152 | self_type& operator=(clear_type*) | |
1153 | { | |
1154 | this->clear(); | |
1155 | return *this; | |
1156 | } | |
1157 | #endif | |
1158 | ||
1159 | self_type& operator=(const base_type& f) | |
1160 | { | |
1161 | self_type(f).swap(*this); | |
1162 | return *this; | |
1163 | } | |
1164 | ||
1165 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
1166 | self_type& operator=(base_type&& f) | |
1167 | { | |
1168 | self_type(static_cast<base_type&&>(f)).swap(*this); | |
1169 | return *this; | |
1170 | } | |
1171 | #endif | |
1172 | }; | |
1173 | ||
1174 | #undef BOOST_FUNCTION_PARTIAL_SPEC | |
1175 | #endif // have partial specialization | |
1176 | ||
1177 | } // end namespace boost | |
1178 | ||
1179 | // Cleanup after ourselves... | |
1180 | #undef BOOST_FUNCTION_VTABLE | |
1181 | #undef BOOST_FUNCTION_COMMA | |
1182 | #undef BOOST_FUNCTION_FUNCTION | |
1183 | #undef BOOST_FUNCTION_FUNCTION_INVOKER | |
1184 | #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER | |
1185 | #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER | |
1186 | #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER | |
1187 | #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER | |
1188 | #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER | |
1189 | #undef BOOST_FUNCTION_MEMBER_INVOKER | |
1190 | #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER | |
1191 | #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER | |
1192 | #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER | |
1193 | #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER | |
1194 | #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER | |
1195 | #undef BOOST_FUNCTION_GET_INVOKER | |
1196 | #undef BOOST_FUNCTION_TEMPLATE_PARMS | |
1197 | #undef BOOST_FUNCTION_TEMPLATE_ARGS | |
1198 | #undef BOOST_FUNCTION_PARMS | |
1199 | #undef BOOST_FUNCTION_PARM | |
1200 | #ifdef BOOST_FUNCTION_ARG | |
1201 | # undef BOOST_FUNCTION_ARG | |
1202 | #endif | |
1203 | #undef BOOST_FUNCTION_ARGS | |
1204 | #undef BOOST_FUNCTION_ARG_TYPE | |
1205 | #undef BOOST_FUNCTION_ARG_TYPES | |
1206 | #undef BOOST_FUNCTION_VOID_RETURN_TYPE | |
1207 | #undef BOOST_FUNCTION_RETURN | |
1208 | ||
1209 | #if defined(BOOST_MSVC) | |
1210 | # pragma warning( pop ) | |
1211 | #endif |