Line data Source code
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 : #ifndef BOOST_FUNCTION_BASE_HEADER
12 : #define BOOST_FUNCTION_BASE_HEADER
13 :
14 : #include <boost/function/function_fwd.hpp>
15 : #include <boost/function_equal.hpp>
16 : #include <boost/core/typeinfo.hpp>
17 : #include <boost/core/ref.hpp>
18 : #include <boost/assert.hpp>
19 : #include <boost/config.hpp>
20 : #include <boost/config/workaround.hpp>
21 : #include <stdexcept>
22 : #include <string>
23 : #include <memory>
24 : #include <new>
25 : #include <type_traits>
26 :
27 : #if defined(BOOST_MSVC)
28 : # pragma warning( push )
29 : # pragma warning( disable : 4793 ) // complaint about native code generation
30 : # pragma warning( disable : 4127 ) // "conditional expression is constant"
31 : #endif
32 :
33 : // retained because used in a test
34 : #define BOOST_FUNCTION_TARGET_FIX(x)
35 :
36 : #define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
37 : typename std::enable_if< !std::is_integral<Functor>::value, Type>::type
38 :
39 : namespace boost {
40 : namespace detail {
41 : namespace function {
42 : class X;
43 :
44 : /**
45 : * A buffer used to store small function objects in
46 : * boost::function. It is a union containing function pointers,
47 : * object pointers, and a structure that resembles a bound
48 : * member function pointer.
49 : */
50 : union function_buffer_members
51 : {
52 : // For pointers to function objects
53 : typedef void* obj_ptr_t;
54 : mutable obj_ptr_t obj_ptr;
55 :
56 : // For pointers to std::type_info objects
57 : struct type_t {
58 : // (get_functor_type_tag, check_functor_type_tag).
59 : const boost::core::typeinfo* type;
60 :
61 : // Whether the type is const-qualified.
62 : bool const_qualified;
63 : // Whether the type is volatile-qualified.
64 : bool volatile_qualified;
65 : } type;
66 :
67 : // For function pointers of all kinds
68 : typedef void (*func_ptr_t)();
69 : mutable func_ptr_t func_ptr;
70 :
71 : #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
72 : # pragma warning(push)
73 : # pragma warning(disable: 5243)
74 : #endif
75 :
76 : // For bound member pointers
77 : struct bound_memfunc_ptr_t {
78 : void (X::*memfunc_ptr)(int);
79 : void* obj_ptr;
80 : } bound_memfunc_ptr;
81 :
82 : #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
83 : # pragma warning(pop)
84 : #endif
85 :
86 : // For references to function objects. We explicitly keep
87 : // track of the cv-qualifiers on the object referenced.
88 : struct obj_ref_t {
89 : mutable void* obj_ptr;
90 : bool is_const_qualified;
91 : bool is_volatile_qualified;
92 : } obj_ref;
93 : };
94 :
95 : union BOOST_SYMBOL_VISIBLE function_buffer
96 : {
97 : // Type-specific union members
98 : mutable function_buffer_members members;
99 :
100 : // To relax aliasing constraints
101 : mutable char data[sizeof(function_buffer_members)];
102 : };
103 :
104 : // The operation type to perform on the given functor/function pointer
105 : enum functor_manager_operation_type {
106 : clone_functor_tag,
107 : move_functor_tag,
108 : destroy_functor_tag,
109 : check_functor_type_tag,
110 : get_functor_type_tag
111 : };
112 :
113 : // Tags used to decide between different types of functions
114 : struct function_ptr_tag {};
115 : struct function_obj_tag {};
116 : struct member_ptr_tag {};
117 : struct function_obj_ref_tag {};
118 :
119 : template<typename F>
120 : class get_function_tag
121 : {
122 : typedef typename std::conditional<std::is_pointer<F>::value,
123 : function_ptr_tag,
124 : function_obj_tag>::type ptr_or_obj_tag;
125 :
126 : typedef typename std::conditional<std::is_member_pointer<F>::value,
127 : member_ptr_tag,
128 : ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
129 :
130 : typedef typename std::conditional<is_reference_wrapper<F>::value,
131 : function_obj_ref_tag,
132 : ptr_or_obj_or_mem_tag>::type or_ref_tag;
133 :
134 : public:
135 : typedef or_ref_tag type;
136 : };
137 :
138 : // The trivial manager does nothing but return the same pointer (if we
139 : // are cloning) or return the null pointer (if we are deleting).
140 : template<typename F>
141 : struct reference_manager
142 : {
143 : static inline void
144 : manage(const function_buffer& in_buffer, function_buffer& out_buffer,
145 : functor_manager_operation_type op)
146 : {
147 : switch (op) {
148 : case clone_functor_tag:
149 : out_buffer.members.obj_ref = in_buffer.members.obj_ref;
150 : return;
151 :
152 : case move_functor_tag:
153 : out_buffer.members.obj_ref = in_buffer.members.obj_ref;
154 : in_buffer.members.obj_ref.obj_ptr = 0;
155 : return;
156 :
157 : case destroy_functor_tag:
158 : out_buffer.members.obj_ref.obj_ptr = 0;
159 : return;
160 :
161 : case check_functor_type_tag:
162 : {
163 : // Check whether we have the same type. We can add
164 : // cv-qualifiers, but we can't take them away.
165 : if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(F)
166 : && (!in_buffer.members.obj_ref.is_const_qualified
167 : || out_buffer.members.type.const_qualified)
168 : && (!in_buffer.members.obj_ref.is_volatile_qualified
169 : || out_buffer.members.type.volatile_qualified))
170 : out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
171 : else
172 : out_buffer.members.obj_ptr = 0;
173 : }
174 : return;
175 :
176 : case get_functor_type_tag:
177 : out_buffer.members.type.type = &BOOST_CORE_TYPEID(F);
178 : out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
179 : out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
180 : return;
181 : }
182 : }
183 : };
184 :
185 : /**
186 : * Determine if boost::function can use the small-object
187 : * optimization with the function object type F.
188 : */
189 : template<typename F>
190 : struct function_allows_small_object_optimization
191 : {
192 : BOOST_STATIC_CONSTANT
193 : (bool,
194 : value = ((sizeof(F) <= sizeof(function_buffer) &&
195 : (std::alignment_of<function_buffer>::value
196 : % std::alignment_of<F>::value == 0))));
197 : };
198 :
199 : template <typename F,typename A>
200 : struct functor_wrapper: public F, public A
201 : {
202 : functor_wrapper( F f, A a ):
203 : F(f),
204 : A(a)
205 : {
206 : }
207 :
208 : functor_wrapper(const functor_wrapper& f) :
209 : F(static_cast<const F&>(f)),
210 : A(static_cast<const A&>(f))
211 : {
212 : }
213 : };
214 :
215 : /**
216 : * The functor_manager class contains a static function "manage" which
217 : * can clone or destroy the given function/function object pointer.
218 : */
219 : template<typename Functor>
220 : struct functor_manager_common
221 : {
222 : typedef Functor functor_type;
223 :
224 : // Function pointers
225 : static inline void
226 101762 : manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
227 : functor_manager_operation_type op)
228 : {
229 101762 : if (op == clone_functor_tag)
230 0 : out_buffer.members.func_ptr = in_buffer.members.func_ptr;
231 101762 : else if (op == move_functor_tag) {
232 0 : out_buffer.members.func_ptr = in_buffer.members.func_ptr;
233 0 : in_buffer.members.func_ptr = 0;
234 101762 : } else if (op == destroy_functor_tag)
235 101762 : out_buffer.members.func_ptr = 0;
236 0 : else if (op == check_functor_type_tag) {
237 0 : if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
238 0 : out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
239 : else
240 0 : out_buffer.members.obj_ptr = 0;
241 0 : } else /* op == get_functor_type_tag */ {
242 0 : out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
243 0 : out_buffer.members.type.const_qualified = false;
244 0 : out_buffer.members.type.volatile_qualified = false;
245 : }
246 101762 : }
247 :
248 : // Function objects that fit in the small-object buffer.
249 : static inline void
250 33286 : manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
251 : functor_manager_operation_type op)
252 : {
253 33286 : if (op == clone_functor_tag) {
254 6628 : const functor_type* in_functor =
255 6628 : reinterpret_cast<const functor_type*>(in_buffer.data);
256 6628 : new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
257 :
258 33286 : } else if (op == move_functor_tag) {
259 13256 : functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
260 13256 : new (reinterpret_cast<void*>(out_buffer.data)) functor_type(std::move(*f));
261 13256 : f->~Functor();
262 26658 : } else if (op == destroy_functor_tag) {
263 : // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
264 13402 : functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data);
265 : (void)f; // suppress warning about the value of f not being used (MSVC)
266 13402 : f->~Functor();
267 13402 : } else if (op == check_functor_type_tag) {
268 0 : if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
269 0 : out_buffer.members.obj_ptr = in_buffer.data;
270 : else
271 0 : out_buffer.members.obj_ptr = 0;
272 0 : } else /* op == get_functor_type_tag */ {
273 0 : out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
274 0 : out_buffer.members.type.const_qualified = false;
275 0 : out_buffer.members.type.volatile_qualified = false;
276 : }
277 33286 : }
278 : };
279 :
280 : template<typename Functor>
281 : struct functor_manager
282 : {
283 : private:
284 : typedef Functor functor_type;
285 :
286 : // Function pointers
287 : static inline void
288 101762 : manager(const function_buffer& in_buffer, function_buffer& out_buffer,
289 : functor_manager_operation_type op, function_ptr_tag)
290 : {
291 101762 : functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
292 101762 : }
293 :
294 : // Function objects that fit in the small-object buffer.
295 : static inline void
296 33286 : manager(const function_buffer& in_buffer, function_buffer& out_buffer,
297 : functor_manager_operation_type op, std::true_type)
298 : {
299 33286 : functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
300 33286 : }
301 :
302 : // Function objects that require heap allocation
303 : static inline void
304 97284 : manager(const function_buffer& in_buffer, function_buffer& out_buffer,
305 : functor_manager_operation_type op, std::false_type)
306 : {
307 97284 : if (op == clone_functor_tag) {
308 : // Clone the functor
309 : // GCC 2.95.3 gets the CV qualifiers wrong here, so we
310 : // can't do the static_cast that we should do.
311 : // jewillco: Changing this to static_cast because GCC 2.95.3 is
312 : // obsolete.
313 23149 : const functor_type* f =
314 23149 : static_cast<const functor_type*>(in_buffer.members.obj_ptr);
315 23149 : functor_type* new_f = new functor_type(*f);
316 23149 : out_buffer.members.obj_ptr = new_f;
317 97284 : } else if (op == move_functor_tag) {
318 46298 : out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
319 46298 : in_buffer.members.obj_ptr = 0;
320 74135 : } else if (op == destroy_functor_tag) {
321 : /* Cast from the void pointer to the functor pointer type */
322 27837 : functor_type* f =
323 27837 : static_cast<functor_type*>(out_buffer.members.obj_ptr);
324 27837 : delete f;
325 27837 : out_buffer.members.obj_ptr = 0;
326 27837 : } else if (op == check_functor_type_tag) {
327 0 : if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
328 0 : out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
329 : else
330 0 : out_buffer.members.obj_ptr = 0;
331 0 : } else /* op == get_functor_type_tag */ {
332 0 : out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
333 0 : out_buffer.members.type.const_qualified = false;
334 0 : out_buffer.members.type.volatile_qualified = false;
335 : }
336 97284 : }
337 :
338 : // For function objects, we determine whether the function
339 : // object can use the small-object optimization buffer or
340 : // whether we need to allocate it on the heap.
341 : static inline void
342 130570 : manager(const function_buffer& in_buffer, function_buffer& out_buffer,
343 : functor_manager_operation_type op, function_obj_tag)
344 : {
345 130570 : manager(in_buffer, out_buffer, op,
346 : std::integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
347 130570 : }
348 :
349 : // For member pointers, we use the small-object optimization buffer.
350 : static inline void
351 : manager(const function_buffer& in_buffer, function_buffer& out_buffer,
352 : functor_manager_operation_type op, member_ptr_tag)
353 : {
354 : manager(in_buffer, out_buffer, op, std::true_type());
355 : }
356 :
357 : public:
358 : /* Dispatch to an appropriate manager based on whether we have a
359 : function pointer or a function object pointer. */
360 : static inline void
361 232332 : manage(const function_buffer& in_buffer, function_buffer& out_buffer,
362 : functor_manager_operation_type op)
363 : {
364 : typedef typename get_function_tag<functor_type>::type tag_type;
365 232332 : if (op == get_functor_type_tag) {
366 0 : out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
367 0 : out_buffer.members.type.const_qualified = false;
368 0 : out_buffer.members.type.volatile_qualified = false;
369 0 : } else {
370 232332 : manager(in_buffer, out_buffer, op, tag_type());
371 : }
372 232332 : }
373 : };
374 :
375 : template<typename Functor, typename Allocator>
376 : struct functor_manager_a
377 : {
378 : private:
379 : typedef Functor functor_type;
380 :
381 : // Function pointers
382 : static inline void
383 : manager(const function_buffer& in_buffer, function_buffer& out_buffer,
384 : functor_manager_operation_type op, function_ptr_tag)
385 : {
386 : functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
387 : }
388 :
389 : // Function objects that fit in the small-object buffer.
390 : static inline void
391 : manager(const function_buffer& in_buffer, function_buffer& out_buffer,
392 : functor_manager_operation_type op, std::true_type)
393 : {
394 : functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
395 : }
396 :
397 : // Function objects that require heap allocation
398 : static inline void
399 : manager(const function_buffer& in_buffer, function_buffer& out_buffer,
400 : functor_manager_operation_type op, std::false_type)
401 : {
402 : typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
403 :
404 : using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
405 : using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
406 :
407 : if (op == clone_functor_tag) {
408 : // Clone the functor
409 : // GCC 2.95.3 gets the CV qualifiers wrong here, so we
410 : // can't do the static_cast that we should do.
411 : const functor_wrapper_type* f =
412 : static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
413 : wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
414 : wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
415 : std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, *f);
416 :
417 : // Get back to the original pointer type
418 : functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
419 : out_buffer.members.obj_ptr = new_f;
420 : } else if (op == move_functor_tag) {
421 : out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
422 : in_buffer.members.obj_ptr = 0;
423 : } else if (op == destroy_functor_tag) {
424 : /* Cast from the void pointer to the functor_wrapper_type */
425 : functor_wrapper_type* victim =
426 : static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
427 : wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
428 : std::allocator_traits<wrapper_allocator_type>::destroy(wrapper_allocator, victim);
429 : wrapper_allocator.deallocate(victim,1);
430 : out_buffer.members.obj_ptr = 0;
431 : } else if (op == check_functor_type_tag) {
432 : if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
433 : out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
434 : else
435 : out_buffer.members.obj_ptr = 0;
436 : } else /* op == get_functor_type_tag */ {
437 : out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
438 : out_buffer.members.type.const_qualified = false;
439 : out_buffer.members.type.volatile_qualified = false;
440 : }
441 : }
442 :
443 : // For function objects, we determine whether the function
444 : // object can use the small-object optimization buffer or
445 : // whether we need to allocate it on the heap.
446 : static inline void
447 : manager(const function_buffer& in_buffer, function_buffer& out_buffer,
448 : functor_manager_operation_type op, function_obj_tag)
449 : {
450 : manager(in_buffer, out_buffer, op,
451 : std::integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
452 : }
453 :
454 : public:
455 : /* Dispatch to an appropriate manager based on whether we have a
456 : function pointer or a function object pointer. */
457 : static inline void
458 : manage(const function_buffer& in_buffer, function_buffer& out_buffer,
459 : functor_manager_operation_type op)
460 : {
461 : typedef typename get_function_tag<functor_type>::type tag_type;
462 : if (op == get_functor_type_tag) {
463 : out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
464 : out_buffer.members.type.const_qualified = false;
465 : out_buffer.members.type.volatile_qualified = false;
466 : } else {
467 : manager(in_buffer, out_buffer, op, tag_type());
468 : }
469 : }
470 : };
471 :
472 : // A type that is only used for comparisons against zero
473 : struct useless_clear_type {};
474 :
475 : /**
476 : * Stores the "manager" portion of the vtable for a
477 : * boost::function object.
478 : */
479 : struct vtable_base
480 : {
481 : void (*manager)(const function_buffer& in_buffer,
482 : function_buffer& out_buffer,
483 : functor_manager_operation_type op);
484 : };
485 : } // end namespace function
486 : } // end namespace detail
487 :
488 : /**
489 : * The function_base class contains the basic elements needed for the
490 : * function1, function2, function3, etc. classes. It is common to all
491 : * functions (and as such can be used to tell if we have one of the
492 : * functionN objects).
493 : */
494 : class function_base
495 : {
496 : public:
497 337232 : function_base() : vtable(0) { }
498 :
499 : /** Determine if the function is empty (i.e., has no target). */
500 611150 : bool empty() const { return !vtable; }
501 :
502 : /** Retrieve the type of the stored function object, or type_id<void>()
503 : if this is empty. */
504 : const boost::core::typeinfo& target_type() const
505 : {
506 : if (!vtable) return BOOST_CORE_TYPEID(void);
507 :
508 : detail::function::function_buffer type;
509 : get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
510 : return *type.members.type.type;
511 : }
512 :
513 : template<typename Functor>
514 : Functor* target()
515 : {
516 : if (!vtable) return 0;
517 :
518 : detail::function::function_buffer type_result;
519 : type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
520 : type_result.members.type.const_qualified = std::is_const<Functor>::value;
521 : type_result.members.type.volatile_qualified = std::is_volatile<Functor>::value;
522 : get_vtable()->manager(functor, type_result,
523 : detail::function::check_functor_type_tag);
524 : return static_cast<Functor*>(type_result.members.obj_ptr);
525 : }
526 :
527 : template<typename Functor>
528 : const Functor* target() const
529 : {
530 : if (!vtable) return 0;
531 :
532 : detail::function::function_buffer type_result;
533 : type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
534 : type_result.members.type.const_qualified = true;
535 : type_result.members.type.volatile_qualified = std::is_volatile<Functor>::value;
536 : get_vtable()->manager(functor, type_result,
537 : detail::function::check_functor_type_tag);
538 : // GCC 2.95.3 gets the CV qualifiers wrong here, so we
539 : // can't do the static_cast that we should do.
540 : return static_cast<const Functor*>(type_result.members.obj_ptr);
541 : }
542 :
543 : template<typename F>
544 : typename std::enable_if< !std::is_function<F>::value, bool >::type
545 : contains(const F& f) const
546 : {
547 : if (const F* fp = this->template target<F>())
548 : {
549 : return function_equal(*fp, f);
550 : } else {
551 : return false;
552 : }
553 : }
554 :
555 : template<typename Fn>
556 : typename std::enable_if< std::is_function<Fn>::value, bool >::type
557 : contains(Fn& f) const
558 : {
559 : typedef Fn* F;
560 : if (const F* fp = this->template target<F>())
561 : {
562 : return function_equal(*fp, &f);
563 : } else {
564 : return false;
565 : }
566 : }
567 :
568 : public: // should be protected, but GCC 2.95.3 will fail to allow access
569 : detail::function::vtable_base* get_vtable() const {
570 : return reinterpret_cast<detail::function::vtable_base*>(
571 : reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
572 : }
573 :
574 336138 : bool has_trivial_copy_and_destroy() const {
575 336138 : return reinterpret_cast<std::size_t>(vtable) & 0x01;
576 : }
577 :
578 : detail::function::vtable_base* vtable;
579 : mutable detail::function::function_buffer functor;
580 : };
581 :
582 : #if defined(BOOST_CLANG)
583 : # pragma clang diagnostic push
584 : # pragma clang diagnostic ignored "-Wweak-vtables"
585 : #endif
586 : /**
587 : * The bad_function_call exception class is thrown when a boost::function
588 : * object is invoked
589 : */
590 : class BOOST_SYMBOL_VISIBLE bad_function_call : public std::runtime_error
591 : {
592 : public:
593 0 : bad_function_call() : std::runtime_error("call to empty boost::function") {}
594 : };
595 : #if defined(BOOST_CLANG)
596 : # pragma clang diagnostic pop
597 : #endif
598 :
599 : inline bool operator==(const function_base& f,
600 : detail::function::useless_clear_type*)
601 : {
602 : return f.empty();
603 : }
604 :
605 : inline bool operator!=(const function_base& f,
606 : detail::function::useless_clear_type*)
607 : {
608 : return !f.empty();
609 : }
610 :
611 : inline bool operator==(detail::function::useless_clear_type*,
612 : const function_base& f)
613 : {
614 : return f.empty();
615 : }
616 :
617 : inline bool operator!=(detail::function::useless_clear_type*,
618 : const function_base& f)
619 : {
620 : return !f.empty();
621 : }
622 :
623 : // Comparisons between boost::function objects and arbitrary function
624 : // objects.
625 :
626 : template<typename Functor>
627 : BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
628 : operator==(const function_base& f, Functor g)
629 : {
630 : if (const Functor* fp = f.template target<Functor>())
631 : return function_equal(*fp, g);
632 : else return false;
633 : }
634 :
635 : template<typename Functor>
636 : BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
637 : operator==(Functor g, const function_base& f)
638 : {
639 : if (const Functor* fp = f.template target<Functor>())
640 : return function_equal(g, *fp);
641 : else return false;
642 : }
643 :
644 : template<typename Functor>
645 : BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
646 : operator!=(const function_base& f, Functor g)
647 : {
648 : if (const Functor* fp = f.template target<Functor>())
649 : return !function_equal(*fp, g);
650 : else return true;
651 : }
652 :
653 : template<typename Functor>
654 : BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
655 : operator!=(Functor g, const function_base& f)
656 : {
657 : if (const Functor* fp = f.template target<Functor>())
658 : return !function_equal(g, *fp);
659 : else return true;
660 : }
661 :
662 : template<typename Functor>
663 : BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
664 : operator==(const function_base& f, reference_wrapper<Functor> g)
665 : {
666 : if (const Functor* fp = f.template target<Functor>())
667 : return fp == g.get_pointer();
668 : else return false;
669 : }
670 :
671 : template<typename Functor>
672 : BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
673 : operator==(reference_wrapper<Functor> g, const function_base& f)
674 : {
675 : if (const Functor* fp = f.template target<Functor>())
676 : return g.get_pointer() == fp;
677 : else return false;
678 : }
679 :
680 : template<typename Functor>
681 : BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
682 : operator!=(const function_base& f, reference_wrapper<Functor> g)
683 : {
684 : if (const Functor* fp = f.template target<Functor>())
685 : return fp != g.get_pointer();
686 : else return true;
687 : }
688 :
689 : template<typename Functor>
690 : BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
691 : operator!=(reference_wrapper<Functor> g, const function_base& f)
692 : {
693 : if (const Functor* fp = f.template target<Functor>())
694 : return g.get_pointer() != fp;
695 : else return true;
696 : }
697 :
698 : namespace detail {
699 : namespace function {
700 : inline bool has_empty_target(const function_base* f)
701 : {
702 : return f->empty();
703 : }
704 :
705 : #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
706 : inline bool has_empty_target(const void*)
707 : {
708 : return false;
709 : }
710 : #else
711 31822 : inline bool has_empty_target(...)
712 : {
713 31822 : return false;
714 : }
715 : #endif
716 : } // end namespace function
717 : } // end namespace detail
718 : } // end namespace boost
719 :
720 : #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
721 :
722 : #if defined(BOOST_MSVC)
723 : # pragma warning( pop )
724 : #endif
725 :
726 : #endif // BOOST_FUNCTION_BASE_HEADER
|