1 | // Boost.Function library |
---|
2 | |
---|
3 | // Copyright Douglas Gregor 2001-2006. Use, modification and |
---|
4 | // distribution is subject to the Boost Software License, Version |
---|
5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
6 | // http://www.boost.org/LICENSE_1_0.txt) |
---|
7 | |
---|
8 | // For more information, see http://www.boost.org |
---|
9 | |
---|
10 | // Note: this header is a header template and must NOT have multiple-inclusion |
---|
11 | // protection. |
---|
12 | #include <boost/function/detail/prologue.hpp> |
---|
13 | |
---|
14 | #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) |
---|
15 | |
---|
16 | #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T) |
---|
17 | |
---|
18 | #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I) |
---|
19 | |
---|
20 | #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY) |
---|
21 | |
---|
22 | #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a) |
---|
23 | |
---|
24 | #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \ |
---|
25 | typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type); |
---|
26 | |
---|
27 | #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY) |
---|
28 | |
---|
29 | // Type of the default allocator |
---|
30 | #ifndef BOOST_NO_STD_ALLOCATOR |
---|
31 | # define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base> |
---|
32 | #else |
---|
33 | # define BOOST_FUNCTION_DEFAULT_ALLOCATOR int |
---|
34 | #endif // BOOST_NO_STD_ALLOCATOR |
---|
35 | |
---|
36 | // Comma if nonzero number of arguments |
---|
37 | #if BOOST_FUNCTION_NUM_ARGS == 0 |
---|
38 | # define BOOST_FUNCTION_COMMA |
---|
39 | #else |
---|
40 | # define BOOST_FUNCTION_COMMA , |
---|
41 | #endif // BOOST_FUNCTION_NUM_ARGS > 0 |
---|
42 | |
---|
43 | // Class names used in this version of the code |
---|
44 | #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS) |
---|
45 | #define BOOST_FUNCTION_FUNCTION_INVOKER \ |
---|
46 | BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) |
---|
47 | #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ |
---|
48 | BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS) |
---|
49 | #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \ |
---|
50 | BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) |
---|
51 | #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \ |
---|
52 | BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) |
---|
53 | #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \ |
---|
54 | BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) |
---|
55 | #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \ |
---|
56 | BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) |
---|
57 | #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ |
---|
58 | BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) |
---|
59 | #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ |
---|
60 | BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) |
---|
61 | #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \ |
---|
62 | BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) |
---|
63 | #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS) |
---|
64 | |
---|
65 | #ifndef BOOST_NO_VOID_RETURNS |
---|
66 | # define BOOST_FUNCTION_VOID_RETURN_TYPE void |
---|
67 | # define BOOST_FUNCTION_RETURN(X) X |
---|
68 | #else |
---|
69 | # define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable |
---|
70 | # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE () |
---|
71 | #endif |
---|
72 | |
---|
73 | #ifdef BOOST_MSVC |
---|
74 | # pragma warning(push) |
---|
75 | # pragma warning(disable: 4127) // conditional expression is constant. |
---|
76 | #endif |
---|
77 | |
---|
78 | #ifdef BOOST_MSVC |
---|
79 | # pragma warning(push) |
---|
80 | # pragma warning(disable: 4127) // conditional expression is constant. |
---|
81 | #endif |
---|
82 | |
---|
83 | namespace boost { |
---|
84 | namespace detail { |
---|
85 | namespace function { |
---|
86 | template< |
---|
87 | typename FunctionPtr, |
---|
88 | typename R BOOST_FUNCTION_COMMA |
---|
89 | BOOST_FUNCTION_TEMPLATE_PARMS |
---|
90 | > |
---|
91 | struct BOOST_FUNCTION_FUNCTION_INVOKER |
---|
92 | { |
---|
93 | static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA |
---|
94 | BOOST_FUNCTION_PARMS) |
---|
95 | { |
---|
96 | FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); |
---|
97 | return f(BOOST_FUNCTION_ARGS); |
---|
98 | } |
---|
99 | }; |
---|
100 | |
---|
101 | template< |
---|
102 | typename FunctionPtr, |
---|
103 | typename R BOOST_FUNCTION_COMMA |
---|
104 | BOOST_FUNCTION_TEMPLATE_PARMS |
---|
105 | > |
---|
106 | struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER |
---|
107 | { |
---|
108 | static BOOST_FUNCTION_VOID_RETURN_TYPE |
---|
109 | invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA |
---|
110 | BOOST_FUNCTION_PARMS) |
---|
111 | |
---|
112 | { |
---|
113 | FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); |
---|
114 | BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS)); |
---|
115 | } |
---|
116 | }; |
---|
117 | |
---|
118 | template< |
---|
119 | typename FunctionObj, |
---|
120 | typename R BOOST_FUNCTION_COMMA |
---|
121 | BOOST_FUNCTION_TEMPLATE_PARMS |
---|
122 | > |
---|
123 | struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER |
---|
124 | { |
---|
125 | static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA |
---|
126 | BOOST_FUNCTION_PARMS) |
---|
127 | |
---|
128 | { |
---|
129 | FunctionObj* f; |
---|
130 | if (function_allows_small_object_optimization<FunctionObj>::value) |
---|
131 | f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data); |
---|
132 | else |
---|
133 | f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); |
---|
134 | return (*f)(BOOST_FUNCTION_ARGS); |
---|
135 | } |
---|
136 | }; |
---|
137 | |
---|
138 | template< |
---|
139 | typename FunctionObj, |
---|
140 | typename R BOOST_FUNCTION_COMMA |
---|
141 | BOOST_FUNCTION_TEMPLATE_PARMS |
---|
142 | > |
---|
143 | struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER |
---|
144 | { |
---|
145 | static BOOST_FUNCTION_VOID_RETURN_TYPE |
---|
146 | invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA |
---|
147 | BOOST_FUNCTION_PARMS) |
---|
148 | |
---|
149 | { |
---|
150 | FunctionObj* f; |
---|
151 | if (function_allows_small_object_optimization<FunctionObj>::value) |
---|
152 | f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data); |
---|
153 | else |
---|
154 | f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); |
---|
155 | BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); |
---|
156 | } |
---|
157 | }; |
---|
158 | |
---|
159 | template< |
---|
160 | typename FunctionObj, |
---|
161 | typename R BOOST_FUNCTION_COMMA |
---|
162 | BOOST_FUNCTION_TEMPLATE_PARMS |
---|
163 | > |
---|
164 | struct BOOST_FUNCTION_FUNCTION_REF_INVOKER |
---|
165 | { |
---|
166 | static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA |
---|
167 | BOOST_FUNCTION_PARMS) |
---|
168 | |
---|
169 | { |
---|
170 | FunctionObj* f = |
---|
171 | reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); |
---|
172 | return (*f)(BOOST_FUNCTION_ARGS); |
---|
173 | } |
---|
174 | }; |
---|
175 | |
---|
176 | template< |
---|
177 | typename FunctionObj, |
---|
178 | typename R BOOST_FUNCTION_COMMA |
---|
179 | BOOST_FUNCTION_TEMPLATE_PARMS |
---|
180 | > |
---|
181 | struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER |
---|
182 | { |
---|
183 | static BOOST_FUNCTION_VOID_RETURN_TYPE |
---|
184 | invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA |
---|
185 | BOOST_FUNCTION_PARMS) |
---|
186 | |
---|
187 | { |
---|
188 | FunctionObj* f = |
---|
189 | reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); |
---|
190 | BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); |
---|
191 | } |
---|
192 | }; |
---|
193 | |
---|
194 | template< |
---|
195 | typename FunctionPtr, |
---|
196 | typename R BOOST_FUNCTION_COMMA |
---|
197 | BOOST_FUNCTION_TEMPLATE_PARMS |
---|
198 | > |
---|
199 | struct BOOST_FUNCTION_GET_FUNCTION_INVOKER |
---|
200 | { |
---|
201 | typedef typename mpl::if_c<(is_void<R>::value), |
---|
202 | BOOST_FUNCTION_VOID_FUNCTION_INVOKER< |
---|
203 | FunctionPtr, |
---|
204 | R BOOST_FUNCTION_COMMA |
---|
205 | BOOST_FUNCTION_TEMPLATE_ARGS |
---|
206 | >, |
---|
207 | BOOST_FUNCTION_FUNCTION_INVOKER< |
---|
208 | FunctionPtr, |
---|
209 | R BOOST_FUNCTION_COMMA |
---|
210 | BOOST_FUNCTION_TEMPLATE_ARGS |
---|
211 | > |
---|
212 | >::type type; |
---|
213 | }; |
---|
214 | |
---|
215 | template< |
---|
216 | typename FunctionObj, |
---|
217 | typename R BOOST_FUNCTION_COMMA |
---|
218 | BOOST_FUNCTION_TEMPLATE_PARMS |
---|
219 | > |
---|
220 | struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER |
---|
221 | { |
---|
222 | typedef typename mpl::if_c<(is_void<R>::value), |
---|
223 | BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER< |
---|
224 | FunctionObj, |
---|
225 | R BOOST_FUNCTION_COMMA |
---|
226 | BOOST_FUNCTION_TEMPLATE_ARGS |
---|
227 | >, |
---|
228 | BOOST_FUNCTION_FUNCTION_OBJ_INVOKER< |
---|
229 | FunctionObj, |
---|
230 | R BOOST_FUNCTION_COMMA |
---|
231 | BOOST_FUNCTION_TEMPLATE_ARGS |
---|
232 | > |
---|
233 | >::type type; |
---|
234 | }; |
---|
235 | |
---|
236 | template< |
---|
237 | typename FunctionObj, |
---|
238 | typename R BOOST_FUNCTION_COMMA |
---|
239 | BOOST_FUNCTION_TEMPLATE_PARMS |
---|
240 | > |
---|
241 | struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER |
---|
242 | { |
---|
243 | typedef typename mpl::if_c<(is_void<R>::value), |
---|
244 | BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER< |
---|
245 | FunctionObj, |
---|
246 | R BOOST_FUNCTION_COMMA |
---|
247 | BOOST_FUNCTION_TEMPLATE_ARGS |
---|
248 | >, |
---|
249 | BOOST_FUNCTION_FUNCTION_REF_INVOKER< |
---|
250 | FunctionObj, |
---|
251 | R BOOST_FUNCTION_COMMA |
---|
252 | BOOST_FUNCTION_TEMPLATE_ARGS |
---|
253 | > |
---|
254 | >::type type; |
---|
255 | }; |
---|
256 | |
---|
257 | /** |
---|
258 | * vtable for a specific boost::function instance. |
---|
259 | */ |
---|
260 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, |
---|
261 | typename Allocator> |
---|
262 | struct BOOST_FUNCTION_VTABLE : vtable_base |
---|
263 | { |
---|
264 | #ifndef BOOST_NO_VOID_RETURNS |
---|
265 | typedef R result_type; |
---|
266 | #else |
---|
267 | typedef typename function_return_type<R>::type result_type; |
---|
268 | #endif // BOOST_NO_VOID_RETURNS |
---|
269 | |
---|
270 | typedef result_type (*invoker_type)(function_buffer& |
---|
271 | BOOST_FUNCTION_COMMA |
---|
272 | BOOST_FUNCTION_TEMPLATE_ARGS); |
---|
273 | |
---|
274 | template<typename F> |
---|
275 | BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0) |
---|
276 | { |
---|
277 | init(f); |
---|
278 | } |
---|
279 | |
---|
280 | template<typename F> |
---|
281 | bool assign_to(F f, function_buffer& functor) |
---|
282 | { |
---|
283 | typedef typename get_function_tag<F>::type tag; |
---|
284 | return assign_to(f, functor, tag()); |
---|
285 | } |
---|
286 | |
---|
287 | void clear(function_buffer& functor) |
---|
288 | { |
---|
289 | if (manager) |
---|
290 | manager(functor, functor, destroy_functor_tag); |
---|
291 | } |
---|
292 | |
---|
293 | private: |
---|
294 | template<typename F> |
---|
295 | void init(F f) |
---|
296 | { |
---|
297 | typedef typename get_function_tag<F>::type tag; |
---|
298 | init(f, tag()); |
---|
299 | } |
---|
300 | |
---|
301 | // Function pointers |
---|
302 | template<typename FunctionPtr> |
---|
303 | void init(FunctionPtr /*f*/, function_ptr_tag) |
---|
304 | { |
---|
305 | typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< |
---|
306 | FunctionPtr, |
---|
307 | R BOOST_FUNCTION_COMMA |
---|
308 | BOOST_FUNCTION_TEMPLATE_ARGS |
---|
309 | >::type |
---|
310 | actual_invoker_type; |
---|
311 | |
---|
312 | invoker = &actual_invoker_type::invoke; |
---|
313 | manager = &functor_manager<FunctionPtr, Allocator>::manage; |
---|
314 | } |
---|
315 | |
---|
316 | template<typename FunctionPtr> |
---|
317 | bool |
---|
318 | assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) |
---|
319 | { |
---|
320 | this->clear(functor); |
---|
321 | if (f) { |
---|
322 | // should be a reinterpret cast, but some compilers insist |
---|
323 | // on giving cv-qualifiers to free functions |
---|
324 | functor.func_ptr = (void (*)())(f); |
---|
325 | return true; |
---|
326 | } else { |
---|
327 | return false; |
---|
328 | } |
---|
329 | } |
---|
330 | |
---|
331 | // Member pointers |
---|
332 | #if BOOST_FUNCTION_NUM_ARGS > 0 |
---|
333 | template<typename MemberPtr> |
---|
334 | void init(MemberPtr f, member_ptr_tag) |
---|
335 | { |
---|
336 | // DPG TBD: Add explicit support for member function |
---|
337 | // objects, so we invoke through mem_fn() but we retain the |
---|
338 | // right target_type() values. |
---|
339 | this->init(mem_fn(f)); |
---|
340 | } |
---|
341 | |
---|
342 | template<typename MemberPtr> |
---|
343 | bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) |
---|
344 | { |
---|
345 | // DPG TBD: Add explicit support for member function |
---|
346 | // objects, so we invoke through mem_fn() but we retain the |
---|
347 | // right target_type() values. |
---|
348 | if (f) { |
---|
349 | this->assign_to(mem_fn(f), functor); |
---|
350 | return true; |
---|
351 | } else { |
---|
352 | return false; |
---|
353 | } |
---|
354 | } |
---|
355 | #endif // BOOST_FUNCTION_NUM_ARGS > 0 |
---|
356 | |
---|
357 | // Function objects |
---|
358 | template<typename FunctionObj> |
---|
359 | void init(FunctionObj /*f*/, function_obj_tag) |
---|
360 | { |
---|
361 | typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< |
---|
362 | FunctionObj, |
---|
363 | R BOOST_FUNCTION_COMMA |
---|
364 | BOOST_FUNCTION_TEMPLATE_ARGS |
---|
365 | >::type |
---|
366 | actual_invoker_type; |
---|
367 | |
---|
368 | invoker = &actual_invoker_type::invoke; |
---|
369 | manager = &functor_manager<FunctionObj, Allocator>::manage; |
---|
370 | } |
---|
371 | |
---|
372 | // Assign to a function object using the small object optimization |
---|
373 | template<typename FunctionObj> |
---|
374 | void |
---|
375 | assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) |
---|
376 | { |
---|
377 | new ((void*)&functor.data) FunctionObj(f); |
---|
378 | } |
---|
379 | |
---|
380 | // Assign to a function object allocated on the heap. |
---|
381 | template<typename FunctionObj> |
---|
382 | void |
---|
383 | assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) |
---|
384 | { |
---|
385 | #ifndef BOOST_NO_STD_ALLOCATOR |
---|
386 | typedef typename Allocator::template rebind<FunctionObj>::other |
---|
387 | allocator_type; |
---|
388 | typedef typename allocator_type::pointer pointer_type; |
---|
389 | |
---|
390 | allocator_type allocator; |
---|
391 | pointer_type copy = allocator.allocate(1); |
---|
392 | allocator.construct(copy, f); |
---|
393 | |
---|
394 | // Get back to the original pointer type |
---|
395 | functor.obj_ptr = static_cast<FunctionObj*>(copy); |
---|
396 | # else |
---|
397 | functor.obj_ptr = new FunctionObj(f); |
---|
398 | # endif // BOOST_NO_STD_ALLOCATOR |
---|
399 | } |
---|
400 | |
---|
401 | template<typename FunctionObj> |
---|
402 | bool |
---|
403 | assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) |
---|
404 | { |
---|
405 | if (!boost::detail::function::has_empty_target(boost::addressof(f))) { |
---|
406 | assign_functor(f, functor, |
---|
407 | mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>()); |
---|
408 | return true; |
---|
409 | } else { |
---|
410 | return false; |
---|
411 | } |
---|
412 | } |
---|
413 | |
---|
414 | // Reference to a function object |
---|
415 | template<typename FunctionObj> |
---|
416 | void |
---|
417 | init(const reference_wrapper<FunctionObj>& /*f*/, function_obj_ref_tag) |
---|
418 | { |
---|
419 | typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< |
---|
420 | FunctionObj, |
---|
421 | R BOOST_FUNCTION_COMMA |
---|
422 | BOOST_FUNCTION_TEMPLATE_ARGS |
---|
423 | >::type |
---|
424 | actual_invoker_type; |
---|
425 | |
---|
426 | invoker = &actual_invoker_type::invoke; |
---|
427 | manager = &reference_manager<FunctionObj>::get; |
---|
428 | } |
---|
429 | |
---|
430 | template<typename FunctionObj> |
---|
431 | bool |
---|
432 | assign_to(const reference_wrapper<FunctionObj>& f, |
---|
433 | function_buffer& functor, function_obj_ref_tag) |
---|
434 | { |
---|
435 | if (!boost::detail::function::has_empty_target(f.get_pointer())) { |
---|
436 | // DPG TBD: We might need to detect constness of |
---|
437 | // FunctionObj to assign into obj_ptr or const_obj_ptr to |
---|
438 | // be truly legit, but no platform in existence makes |
---|
439 | // const void* different from void*. |
---|
440 | functor.const_obj_ptr = f.get_pointer(); |
---|
441 | return true; |
---|
442 | } else { |
---|
443 | return false; |
---|
444 | } |
---|
445 | } |
---|
446 | |
---|
447 | public: |
---|
448 | invoker_type invoker; |
---|
449 | }; |
---|
450 | } // end namespace function |
---|
451 | } // end namespace detail |
---|
452 | |
---|
453 | template< |
---|
454 | typename R BOOST_FUNCTION_COMMA |
---|
455 | BOOST_FUNCTION_TEMPLATE_PARMS, |
---|
456 | typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR |
---|
457 | > |
---|
458 | class BOOST_FUNCTION_FUNCTION : public function_base |
---|
459 | { |
---|
460 | public: |
---|
461 | #ifndef BOOST_NO_VOID_RETURNS |
---|
462 | typedef R result_type; |
---|
463 | #else |
---|
464 | typedef typename boost::detail::function::function_return_type<R>::type |
---|
465 | result_type; |
---|
466 | #endif // BOOST_NO_VOID_RETURNS |
---|
467 | |
---|
468 | private: |
---|
469 | typedef boost::detail::function::BOOST_FUNCTION_VTABLE< |
---|
470 | R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Allocator> |
---|
471 | vtable_type; |
---|
472 | |
---|
473 | struct clear_type {}; |
---|
474 | |
---|
475 | public: |
---|
476 | BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); |
---|
477 | |
---|
478 | // add signature for boost::lambda |
---|
479 | template<typename Args> |
---|
480 | struct sig |
---|
481 | { |
---|
482 | typedef result_type type; |
---|
483 | }; |
---|
484 | |
---|
485 | #if BOOST_FUNCTION_NUM_ARGS == 1 |
---|
486 | typedef T0 argument_type; |
---|
487 | #elif BOOST_FUNCTION_NUM_ARGS == 2 |
---|
488 | typedef T0 first_argument_type; |
---|
489 | typedef T1 second_argument_type; |
---|
490 | #endif |
---|
491 | |
---|
492 | BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS); |
---|
493 | BOOST_FUNCTION_ARG_TYPES |
---|
494 | |
---|
495 | typedef Allocator allocator_type; |
---|
496 | typedef BOOST_FUNCTION_FUNCTION self_type; |
---|
497 | |
---|
498 | BOOST_FUNCTION_FUNCTION() : function_base() { } |
---|
499 | |
---|
500 | // MSVC chokes if the following two constructors are collapsed into |
---|
501 | // one with a default parameter. |
---|
502 | template<typename Functor> |
---|
503 | BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f |
---|
504 | #ifndef BOOST_NO_SFINAE |
---|
505 | ,typename enable_if_c< |
---|
506 | (boost::type_traits::ice_not< |
---|
507 | (is_integral<Functor>::value)>::value), |
---|
508 | int>::type = 0 |
---|
509 | #endif // BOOST_NO_SFINAE |
---|
510 | ) : |
---|
511 | function_base() |
---|
512 | { |
---|
513 | this->assign_to(f); |
---|
514 | } |
---|
515 | |
---|
516 | #ifndef BOOST_NO_SFINAE |
---|
517 | BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { } |
---|
518 | #else |
---|
519 | BOOST_FUNCTION_FUNCTION(int zero) : function_base() |
---|
520 | { |
---|
521 | BOOST_ASSERT(zero == 0); |
---|
522 | } |
---|
523 | #endif |
---|
524 | |
---|
525 | BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base() |
---|
526 | { |
---|
527 | this->assign_to_own(f); |
---|
528 | } |
---|
529 | |
---|
530 | ~BOOST_FUNCTION_FUNCTION() { clear(); } |
---|
531 | |
---|
532 | #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) |
---|
533 | // MSVC 6.0 and prior require all definitions to be inline, but |
---|
534 | // these definitions can become very costly. |
---|
535 | result_type operator()(BOOST_FUNCTION_PARMS) const |
---|
536 | { |
---|
537 | if (this->empty()) |
---|
538 | boost::throw_exception(bad_function_call()); |
---|
539 | |
---|
540 | return static_cast<vtable_type*>(vtable)->invoker |
---|
541 | (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); |
---|
542 | } |
---|
543 | #else |
---|
544 | result_type operator()(BOOST_FUNCTION_PARMS) const; |
---|
545 | #endif |
---|
546 | |
---|
547 | // The distinction between when to use BOOST_FUNCTION_FUNCTION and |
---|
548 | // when to use self_type is obnoxious. MSVC cannot handle self_type as |
---|
549 | // the return type of these assignment operators, but Borland C++ cannot |
---|
550 | // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to |
---|
551 | // construct. |
---|
552 | template<typename Functor> |
---|
553 | #ifndef BOOST_NO_SFINAE |
---|
554 | typename enable_if_c< |
---|
555 | (boost::type_traits::ice_not< |
---|
556 | (is_integral<Functor>::value)>::value), |
---|
557 | BOOST_FUNCTION_FUNCTION&>::type |
---|
558 | #else |
---|
559 | BOOST_FUNCTION_FUNCTION& |
---|
560 | #endif |
---|
561 | operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) |
---|
562 | { |
---|
563 | this->clear(); |
---|
564 | try { |
---|
565 | this->assign_to(f); |
---|
566 | } catch (...) { |
---|
567 | vtable = 0; |
---|
568 | throw; |
---|
569 | } |
---|
570 | return *this; |
---|
571 | } |
---|
572 | |
---|
573 | #ifndef BOOST_NO_SFINAE |
---|
574 | BOOST_FUNCTION_FUNCTION& operator=(clear_type*) |
---|
575 | { |
---|
576 | this->clear(); |
---|
577 | return *this; |
---|
578 | } |
---|
579 | #else |
---|
580 | BOOST_FUNCTION_FUNCTION& operator=(int zero) |
---|
581 | { |
---|
582 | BOOST_ASSERT(zero == 0); |
---|
583 | this->clear(); |
---|
584 | return *this; |
---|
585 | } |
---|
586 | #endif |
---|
587 | |
---|
588 | // Assignment from another BOOST_FUNCTION_FUNCTION |
---|
589 | BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) |
---|
590 | { |
---|
591 | if (&f == this) |
---|
592 | return *this; |
---|
593 | |
---|
594 | this->clear(); |
---|
595 | try { |
---|
596 | this->assign_to_own(f); |
---|
597 | } catch (...) { |
---|
598 | vtable = 0; |
---|
599 | throw; |
---|
600 | } |
---|
601 | return *this; |
---|
602 | } |
---|
603 | |
---|
604 | void swap(BOOST_FUNCTION_FUNCTION& other) |
---|
605 | { |
---|
606 | if (&other == this) |
---|
607 | return; |
---|
608 | |
---|
609 | BOOST_FUNCTION_FUNCTION tmp = *this; |
---|
610 | *this = other; |
---|
611 | other = tmp; |
---|
612 | } |
---|
613 | |
---|
614 | // Clear out a target, if there is one |
---|
615 | void clear() |
---|
616 | { |
---|
617 | if (vtable) { |
---|
618 | static_cast<vtable_type*>(vtable)->clear(this->functor); |
---|
619 | vtable = 0; |
---|
620 | } |
---|
621 | } |
---|
622 | |
---|
623 | #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG) |
---|
624 | // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it |
---|
625 | operator bool () const { return !this->empty(); } |
---|
626 | #else |
---|
627 | private: |
---|
628 | struct dummy { |
---|
629 | void nonnull() {}; |
---|
630 | }; |
---|
631 | |
---|
632 | typedef void (dummy::*safe_bool)(); |
---|
633 | |
---|
634 | public: |
---|
635 | operator safe_bool () const |
---|
636 | { return (this->empty())? 0 : &dummy::nonnull; } |
---|
637 | |
---|
638 | bool operator!() const |
---|
639 | { return this->empty(); } |
---|
640 | #endif |
---|
641 | |
---|
642 | private: |
---|
643 | void assign_to_own(const BOOST_FUNCTION_FUNCTION& f) |
---|
644 | { |
---|
645 | if (!f.empty()) { |
---|
646 | this->vtable = f.vtable; |
---|
647 | f.vtable->manager(f.functor, this->functor, |
---|
648 | boost::detail::function::clone_functor_tag); |
---|
649 | } |
---|
650 | } |
---|
651 | |
---|
652 | template<typename Functor> |
---|
653 | void assign_to(Functor f) |
---|
654 | { |
---|
655 | static vtable_type stored_vtable(f); |
---|
656 | if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable; |
---|
657 | else vtable = 0; |
---|
658 | } |
---|
659 | }; |
---|
660 | |
---|
661 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS , |
---|
662 | typename Allocator> |
---|
663 | inline void swap(BOOST_FUNCTION_FUNCTION< |
---|
664 | R BOOST_FUNCTION_COMMA |
---|
665 | BOOST_FUNCTION_TEMPLATE_ARGS , |
---|
666 | Allocator |
---|
667 | >& f1, |
---|
668 | BOOST_FUNCTION_FUNCTION< |
---|
669 | R BOOST_FUNCTION_COMMA |
---|
670 | BOOST_FUNCTION_TEMPLATE_ARGS, |
---|
671 | Allocator |
---|
672 | >& f2) |
---|
673 | { |
---|
674 | f1.swap(f2); |
---|
675 | } |
---|
676 | |
---|
677 | #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) |
---|
678 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, |
---|
679 | typename Allocator> |
---|
680 | typename BOOST_FUNCTION_FUNCTION< |
---|
681 | R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, |
---|
682 | Allocator>::result_type |
---|
683 | BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, |
---|
684 | |
---|
685 | Allocator> |
---|
686 | ::operator()(BOOST_FUNCTION_PARMS) const |
---|
687 | { |
---|
688 | if (this->empty()) |
---|
689 | boost::throw_exception(bad_function_call()); |
---|
690 | |
---|
691 | return static_cast<vtable_type*>(vtable)->invoker |
---|
692 | (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); |
---|
693 | } |
---|
694 | #endif |
---|
695 | |
---|
696 | // Poison comparisons between boost::function objects of the same type. |
---|
697 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS , |
---|
698 | typename Allocator> |
---|
699 | void operator==(const BOOST_FUNCTION_FUNCTION< |
---|
700 | R BOOST_FUNCTION_COMMA |
---|
701 | BOOST_FUNCTION_TEMPLATE_ARGS , |
---|
702 | Allocator>&, |
---|
703 | const BOOST_FUNCTION_FUNCTION< |
---|
704 | R BOOST_FUNCTION_COMMA |
---|
705 | BOOST_FUNCTION_TEMPLATE_ARGS , |
---|
706 | Allocator>&); |
---|
707 | template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS , |
---|
708 | typename Allocator> |
---|
709 | void operator!=(const BOOST_FUNCTION_FUNCTION< |
---|
710 | R BOOST_FUNCTION_COMMA |
---|
711 | BOOST_FUNCTION_TEMPLATE_ARGS , |
---|
712 | Allocator>&, |
---|
713 | const BOOST_FUNCTION_FUNCTION< |
---|
714 | R BOOST_FUNCTION_COMMA |
---|
715 | BOOST_FUNCTION_TEMPLATE_ARGS , |
---|
716 | Allocator>&); |
---|
717 | |
---|
718 | #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) |
---|
719 | |
---|
720 | #if BOOST_FUNCTION_NUM_ARGS == 0 |
---|
721 | #define BOOST_FUNCTION_PARTIAL_SPEC R (void) |
---|
722 | #else |
---|
723 | #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)) |
---|
724 | #endif |
---|
725 | |
---|
726 | template<typename R BOOST_FUNCTION_COMMA |
---|
727 | BOOST_FUNCTION_TEMPLATE_PARMS, |
---|
728 | typename Allocator> |
---|
729 | class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator> |
---|
730 | : public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS |
---|
731 | BOOST_FUNCTION_COMMA Allocator> |
---|
732 | { |
---|
733 | typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS |
---|
734 | BOOST_FUNCTION_COMMA Allocator> base_type; |
---|
735 | typedef function self_type; |
---|
736 | |
---|
737 | struct clear_type {}; |
---|
738 | |
---|
739 | public: |
---|
740 | typedef typename base_type::allocator_type allocator_type; |
---|
741 | |
---|
742 | function() : base_type() {} |
---|
743 | |
---|
744 | template<typename Functor> |
---|
745 | function(Functor f |
---|
746 | #ifndef BOOST_NO_SFINAE |
---|
747 | ,typename enable_if_c< |
---|
748 | (boost::type_traits::ice_not< |
---|
749 | (is_integral<Functor>::value)>::value), |
---|
750 | int>::type = 0 |
---|
751 | #endif |
---|
752 | ) : |
---|
753 | base_type(f) |
---|
754 | { |
---|
755 | } |
---|
756 | |
---|
757 | #ifndef BOOST_NO_SFINAE |
---|
758 | function(clear_type*) : base_type() {} |
---|
759 | #endif |
---|
760 | |
---|
761 | function(const self_type& f) : base_type(static_cast<const base_type&>(f)){} |
---|
762 | |
---|
763 | function(const base_type& f) : base_type(static_cast<const base_type&>(f)){} |
---|
764 | |
---|
765 | self_type& operator=(const self_type& f) |
---|
766 | { |
---|
767 | self_type(f).swap(*this); |
---|
768 | return *this; |
---|
769 | } |
---|
770 | |
---|
771 | template<typename Functor> |
---|
772 | #ifndef BOOST_NO_SFINAE |
---|
773 | typename enable_if_c< |
---|
774 | (boost::type_traits::ice_not< |
---|
775 | (is_integral<Functor>::value)>::value), |
---|
776 | self_type&>::type |
---|
777 | #else |
---|
778 | self_type& |
---|
779 | #endif |
---|
780 | operator=(Functor f) |
---|
781 | { |
---|
782 | self_type(f).swap(*this); |
---|
783 | return *this; |
---|
784 | } |
---|
785 | |
---|
786 | #ifndef BOOST_NO_SFINAE |
---|
787 | self_type& operator=(clear_type*) |
---|
788 | { |
---|
789 | this->clear(); |
---|
790 | return *this; |
---|
791 | } |
---|
792 | #endif |
---|
793 | |
---|
794 | self_type& operator=(const base_type& f) |
---|
795 | { |
---|
796 | self_type(f).swap(*this); |
---|
797 | return *this; |
---|
798 | } |
---|
799 | }; |
---|
800 | |
---|
801 | #ifdef BOOST_MSVC |
---|
802 | # pragma warning(pop) |
---|
803 | #endif |
---|
804 | |
---|
805 | #undef BOOST_FUNCTION_PARTIAL_SPEC |
---|
806 | #endif // have partial specialization |
---|
807 | |
---|
808 | } // end namespace boost |
---|
809 | |
---|
810 | #ifdef BOOST_MSVC |
---|
811 | # pragma warning(pop) |
---|
812 | #endif |
---|
813 | |
---|
814 | // Cleanup after ourselves... |
---|
815 | #undef BOOST_FUNCTION_VTABLE |
---|
816 | #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR |
---|
817 | #undef BOOST_FUNCTION_COMMA |
---|
818 | #undef BOOST_FUNCTION_FUNCTION |
---|
819 | #undef BOOST_FUNCTION_FUNCTION_INVOKER |
---|
820 | #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER |
---|
821 | #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER |
---|
822 | #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER |
---|
823 | #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER |
---|
824 | #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER |
---|
825 | #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER |
---|
826 | #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER |
---|
827 | #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER |
---|
828 | #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER |
---|
829 | #undef BOOST_FUNCTION_TEMPLATE_PARMS |
---|
830 | #undef BOOST_FUNCTION_TEMPLATE_ARGS |
---|
831 | #undef BOOST_FUNCTION_PARMS |
---|
832 | #undef BOOST_FUNCTION_PARM |
---|
833 | #undef BOOST_FUNCTION_ARGS |
---|
834 | #undef BOOST_FUNCTION_ARG_TYPE |
---|
835 | #undef BOOST_FUNCTION_ARG_TYPES |
---|
836 | #undef BOOST_FUNCTION_VOID_RETURN_TYPE |
---|
837 | #undef BOOST_FUNCTION_RETURN |
---|