fix doc example typo
[boost.git] / boost / function / function_base.hpp
blob2cc6bf61999d59418bd8b7f8edb3308c551e6bc4
1 // Boost.Function library
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)
9 // For more information, see http://www.boost.org
11 #ifndef BOOST_FUNCTION_BASE_HEADER
12 #define BOOST_FUNCTION_BASE_HEADER
14 #include <stdexcept>
15 #include <string>
16 #include <memory>
17 #include <new>
18 #include <typeinfo>
19 #include <boost/config.hpp>
20 #include <boost/assert.hpp>
21 #include <boost/integer.hpp>
22 #include <boost/type_traits/has_trivial_copy.hpp>
23 #include <boost/type_traits/has_trivial_destructor.hpp>
24 #include <boost/type_traits/is_const.hpp>
25 #include <boost/type_traits/is_integral.hpp>
26 #include <boost/type_traits/is_volatile.hpp>
27 #include <boost/type_traits/composite_traits.hpp>
28 #include <boost/type_traits/ice.hpp>
29 #include <boost/ref.hpp>
30 #include <boost/mpl/if.hpp>
31 #include <boost/detail/workaround.hpp>
32 #include <boost/type_traits/alignment_of.hpp>
33 #ifndef BOOST_NO_SFINAE
34 # include "boost/utility/enable_if.hpp"
35 #else
36 # include "boost/mpl/bool.hpp"
37 #endif
38 #include <boost/function_equal.hpp>
39 #include <boost/function/function_fwd.hpp>
41 #if defined(BOOST_MSVC)
42 # pragma warning( push )
43 # pragma warning( disable : 4793 ) // complaint about native code generation
44 # pragma warning( disable : 4127 ) // "conditional expression is constant"
45 #endif
47 // Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
48 #ifdef BOOST_NO_STD_TYPEINFO
49 // Embedded VC++ does not have type_info in namespace std
50 # define BOOST_FUNCTION_STD_NS
51 #else
52 # define BOOST_FUNCTION_STD_NS std
53 #endif
55 // Borrowed from Boost.Python library: determines the cases where we
56 // need to use std::type_info::name to compare instead of operator==.
57 # if (defined(__GNUC__) && __GNUC__ >= 3) \
58 || defined(_AIX) \
59 || ( defined(__sgi) && defined(__host_mips))
60 # include <cstring>
61 # define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
62 (std::strcmp((X).name(),(Y).name()) == 0)
63 # else
64 # define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
65 #endif
67 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
68 # define BOOST_FUNCTION_TARGET_FIX(x) x
69 #else
70 # define BOOST_FUNCTION_TARGET_FIX(x)
71 #endif // not MSVC
73 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x5A0)
74 # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
75 typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
76 (::boost::is_integral<Functor>::value)>::value), \
77 Type>::type
78 #else
79 // BCC doesn't recognize this depends on a template argument and complains
80 // about the use of 'typename'
81 # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
82 ::boost::enable_if_c<(::boost::type_traits::ice_not< \
83 (::boost::is_integral<Functor>::value)>::value), \
84 Type>::type
85 #endif
87 namespace boost {
88 namespace detail {
89 namespace function {
90 class X;
92 /**
93 * A buffer used to store small function objects in
94 * boost::function. It is a union containing function pointers,
95 * object pointers, and a structure that resembles a bound
96 * member function pointer.
98 union function_buffer
100 // For pointers to function objects
101 mutable void* obj_ptr;
103 // For pointers to std::type_info objects
104 struct type_t {
105 // (get_functor_type_tag, check_functor_type_tag).
106 const BOOST_FUNCTION_STD_NS::type_info* type;
108 // Whether the type is const-qualified.
109 bool const_qualified;
110 // Whether the type is volatile-qualified.
111 bool volatile_qualified;
112 } type;
114 // For function pointers of all kinds
115 mutable void (*func_ptr)();
117 // For bound member pointers
118 struct bound_memfunc_ptr_t {
119 void (X::*memfunc_ptr)(int);
120 void* obj_ptr;
121 } bound_memfunc_ptr;
123 // For references to function objects. We explicitly keep
124 // track of the cv-qualifiers on the object referenced.
125 struct obj_ref_t {
126 mutable void* obj_ptr;
127 bool is_const_qualified;
128 bool is_volatile_qualified;
129 } obj_ref;
131 // To relax aliasing constraints
132 mutable char data;
136 * The unusable class is a placeholder for unused function arguments
137 * It is also completely unusable except that it constructable from
138 * anything. This helps compilers without partial specialization to
139 * handle Boost.Function objects returning void.
141 struct unusable
143 unusable() {}
144 template<typename T> unusable(const T&) {}
147 /* Determine the return type. This supports compilers that do not support
148 * void returns or partial specialization by silently changing the return
149 * type to "unusable".
151 template<typename T> struct function_return_type { typedef T type; };
153 template<>
154 struct function_return_type<void>
156 typedef unusable type;
159 // The operation type to perform on the given functor/function pointer
160 enum functor_manager_operation_type {
161 clone_functor_tag,
162 move_functor_tag,
163 destroy_functor_tag,
164 check_functor_type_tag,
165 get_functor_type_tag
168 // Tags used to decide between different types of functions
169 struct function_ptr_tag {};
170 struct function_obj_tag {};
171 struct member_ptr_tag {};
172 struct function_obj_ref_tag {};
174 template<typename F>
175 class get_function_tag
177 typedef typename mpl::if_c<(is_pointer<F>::value),
178 function_ptr_tag,
179 function_obj_tag>::type ptr_or_obj_tag;
181 typedef typename mpl::if_c<(is_member_pointer<F>::value),
182 member_ptr_tag,
183 ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
185 typedef typename mpl::if_c<(is_reference_wrapper<F>::value),
186 function_obj_ref_tag,
187 ptr_or_obj_or_mem_tag>::type or_ref_tag;
189 public:
190 typedef or_ref_tag type;
193 // The trivial manager does nothing but return the same pointer (if we
194 // are cloning) or return the null pointer (if we are deleting).
195 template<typename F>
196 struct reference_manager
198 static inline void
199 manage(const function_buffer& in_buffer, function_buffer& out_buffer,
200 functor_manager_operation_type op)
202 switch (op) {
203 case clone_functor_tag:
204 out_buffer.obj_ref.obj_ptr = in_buffer.obj_ref.obj_ptr;
205 return;
207 case move_functor_tag:
208 out_buffer.obj_ref.obj_ptr = in_buffer.obj_ref.obj_ptr;
209 in_buffer.obj_ref.obj_ptr = 0;
210 return;
212 case destroy_functor_tag:
213 out_buffer.obj_ref.obj_ptr = 0;
214 return;
216 case check_functor_type_tag:
218 const BOOST_FUNCTION_STD_NS::type_info& check_type
219 = *out_buffer.type.type;
221 // Check whether we have the same type. We can add
222 // cv-qualifiers, but we can't take them away.
223 if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F))
224 && (!in_buffer.obj_ref.is_const_qualified
225 || out_buffer.type.const_qualified)
226 && (!in_buffer.obj_ref.is_volatile_qualified
227 || out_buffer.type.volatile_qualified))
228 out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
229 else
230 out_buffer.obj_ptr = 0;
232 return;
234 case get_functor_type_tag:
235 out_buffer.type.type = &typeid(F);
236 out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
237 out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
238 return;
244 * Determine if boost::function can use the small-object
245 * optimization with the function object type F.
247 template<typename F>
248 struct function_allows_small_object_optimization
250 BOOST_STATIC_CONSTANT
251 (bool,
252 value = ((sizeof(F) <= sizeof(function_buffer) &&
253 (alignment_of<function_buffer>::value
254 % alignment_of<F>::value == 0))));
257 template <typename F,typename A>
258 struct functor_wrapper: public F, public A
260 functor_wrapper( F f, A a ):
261 F(f),
262 A(a)
268 * The functor_manager class contains a static function "manage" which
269 * can clone or destroy the given function/function object pointer.
271 template<typename Functor>
272 struct functor_manager_common
274 typedef Functor functor_type;
276 // Function pointers
277 static inline void
278 manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
279 functor_manager_operation_type op)
281 if (op == clone_functor_tag)
282 out_buffer.func_ptr = in_buffer.func_ptr;
283 else if (op == move_functor_tag) {
284 out_buffer.func_ptr = in_buffer.func_ptr;
285 in_buffer.func_ptr = 0;
286 } else if (op == destroy_functor_tag)
287 out_buffer.func_ptr = 0;
288 else if (op == check_functor_type_tag) {
289 const BOOST_FUNCTION_STD_NS::type_info& check_type
290 = *out_buffer.type.type;
291 if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
292 out_buffer.obj_ptr = &in_buffer.func_ptr;
293 else
294 out_buffer.obj_ptr = 0;
295 } else /* op == get_functor_type_tag */ {
296 out_buffer.type.type = &typeid(Functor);
297 out_buffer.type.const_qualified = false;
298 out_buffer.type.volatile_qualified = false;
302 // Function objects that fit in the small-object buffer.
303 static inline void
304 manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
305 functor_manager_operation_type op)
307 if (op == clone_functor_tag || op == move_functor_tag) {
308 const functor_type* in_functor =
309 reinterpret_cast<const functor_type*>(&in_buffer.data);
310 new ((void*)&out_buffer.data) functor_type(*in_functor);
312 if (op == move_functor_tag) {
313 reinterpret_cast<functor_type*>(&in_buffer.data)->~Functor();
315 } else if (op == destroy_functor_tag) {
316 // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
317 reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
318 } else if (op == check_functor_type_tag) {
319 const BOOST_FUNCTION_STD_NS::type_info& check_type
320 = *out_buffer.type.type;
321 if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
322 out_buffer.obj_ptr = &in_buffer.data;
323 else
324 out_buffer.obj_ptr = 0;
325 } else /* op == get_functor_type_tag */ {
326 out_buffer.type.type = &typeid(Functor);
327 out_buffer.type.const_qualified = false;
328 out_buffer.type.volatile_qualified = false;
333 template<typename Functor>
334 struct functor_manager
336 private:
337 typedef Functor functor_type;
339 // Function pointers
340 static inline void
341 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
342 functor_manager_operation_type op, function_ptr_tag)
344 functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
347 // Function objects that fit in the small-object buffer.
348 static inline void
349 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
350 functor_manager_operation_type op, mpl::true_)
352 functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
355 // Function objects that require heap allocation
356 static inline void
357 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
358 functor_manager_operation_type op, mpl::false_)
360 if (op == clone_functor_tag) {
361 // Clone the functor
362 // GCC 2.95.3 gets the CV qualifiers wrong here, so we
363 // can't do the static_cast that we should do.
364 const functor_type* f =
365 (const functor_type*)(in_buffer.obj_ptr);
366 functor_type* new_f = new functor_type(*f);
367 out_buffer.obj_ptr = new_f;
368 } else if (op == move_functor_tag) {
369 out_buffer.obj_ptr = in_buffer.obj_ptr;
370 in_buffer.obj_ptr = 0;
371 } else if (op == destroy_functor_tag) {
372 /* Cast from the void pointer to the functor pointer type */
373 functor_type* f =
374 static_cast<functor_type*>(out_buffer.obj_ptr);
375 delete f;
376 out_buffer.obj_ptr = 0;
377 } else if (op == check_functor_type_tag) {
378 const BOOST_FUNCTION_STD_NS::type_info& check_type
379 = *out_buffer.type.type;
380 if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
381 out_buffer.obj_ptr = in_buffer.obj_ptr;
382 else
383 out_buffer.obj_ptr = 0;
384 } else /* op == get_functor_type_tag */ {
385 out_buffer.type.type = &typeid(Functor);
386 out_buffer.type.const_qualified = false;
387 out_buffer.type.volatile_qualified = false;
391 // For function objects, we determine whether the function
392 // object can use the small-object optimization buffer or
393 // whether we need to allocate it on the heap.
394 static inline void
395 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
396 functor_manager_operation_type op, function_obj_tag)
398 manager(in_buffer, out_buffer, op,
399 mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
402 // For member pointers, we use the small-object optimization buffer.
403 static inline void
404 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
405 functor_manager_operation_type op, member_ptr_tag)
407 manager(in_buffer, out_buffer, op, mpl::true_());
410 public:
411 /* Dispatch to an appropriate manager based on whether we have a
412 function pointer or a function object pointer. */
413 static inline void
414 manage(const function_buffer& in_buffer, function_buffer& out_buffer,
415 functor_manager_operation_type op)
417 typedef typename get_function_tag<functor_type>::type tag_type;
418 switch (op) {
419 case get_functor_type_tag:
420 out_buffer.type.type = &typeid(functor_type);
421 out_buffer.type.const_qualified = false;
422 out_buffer.type.volatile_qualified = false;
423 return;
425 default:
426 manager(in_buffer, out_buffer, op, tag_type());
427 return;
432 template<typename Functor, typename Allocator>
433 struct functor_manager_a
435 private:
436 typedef Functor functor_type;
438 // Function pointers
439 static inline void
440 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
441 functor_manager_operation_type op, function_ptr_tag)
443 functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
446 // Function objects that fit in the small-object buffer.
447 static inline void
448 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
449 functor_manager_operation_type op, mpl::true_)
451 functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
454 // Function objects that require heap allocation
455 static inline void
456 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
457 functor_manager_operation_type op, mpl::false_)
459 typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
460 typedef typename Allocator::template rebind<functor_wrapper_type>::other
461 wrapper_allocator_type;
462 typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
464 if (op == clone_functor_tag) {
465 // Clone the functor
466 // GCC 2.95.3 gets the CV qualifiers wrong here, so we
467 // can't do the static_cast that we should do.
468 const functor_wrapper_type* f =
469 (const functor_wrapper_type*)(in_buffer.obj_ptr);
470 wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
471 wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
472 wrapper_allocator.construct(copy, *f);
474 // Get back to the original pointer type
475 functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
476 out_buffer.obj_ptr = new_f;
477 } else if (op == move_functor_tag) {
478 out_buffer.obj_ptr = in_buffer.obj_ptr;
479 in_buffer.obj_ptr = 0;
480 } else if (op == destroy_functor_tag) {
481 /* Cast from the void pointer to the functor_wrapper_type */
482 functor_wrapper_type* victim =
483 static_cast<functor_wrapper_type*>(in_buffer.obj_ptr);
484 wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
485 wrapper_allocator.destroy(victim);
486 wrapper_allocator.deallocate(victim,1);
487 out_buffer.obj_ptr = 0;
488 } else if (op == check_functor_type_tag) {
489 const BOOST_FUNCTION_STD_NS::type_info& check_type
490 = *out_buffer.type.type;
491 if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
492 out_buffer.obj_ptr = in_buffer.obj_ptr;
493 else
494 out_buffer.obj_ptr = 0;
495 } else /* op == get_functor_type_tag */ {
496 out_buffer.type.type = &typeid(Functor);
497 out_buffer.type.const_qualified = false;
498 out_buffer.type.volatile_qualified = false;
502 // For function objects, we determine whether the function
503 // object can use the small-object optimization buffer or
504 // whether we need to allocate it on the heap.
505 static inline void
506 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
507 functor_manager_operation_type op, function_obj_tag)
509 manager(in_buffer, out_buffer, op,
510 mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
513 public:
514 /* Dispatch to an appropriate manager based on whether we have a
515 function pointer or a function object pointer. */
516 static inline void
517 manage(const function_buffer& in_buffer, function_buffer& out_buffer,
518 functor_manager_operation_type op)
520 typedef typename get_function_tag<functor_type>::type tag_type;
521 switch (op) {
522 case get_functor_type_tag:
523 out_buffer.type.type = &typeid(functor_type);
524 out_buffer.type.const_qualified = false;
525 out_buffer.type.volatile_qualified = false;
526 return;
528 default:
529 manager(in_buffer, out_buffer, op, tag_type());
530 return;
535 // A type that is only used for comparisons against zero
536 struct useless_clear_type {};
538 #ifdef BOOST_NO_SFINAE
539 // These routines perform comparisons between a Boost.Function
540 // object and an arbitrary function object (when the last
541 // parameter is mpl::bool_<false>) or against zero (when the
542 // last parameter is mpl::bool_<true>). They are only necessary
543 // for compilers that don't support SFINAE.
544 template<typename Function, typename Functor>
545 bool
546 compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
547 { return f.empty(); }
549 template<typename Function, typename Functor>
550 bool
551 compare_not_equal(const Function& f, const Functor&, int,
552 mpl::bool_<true>)
553 { return !f.empty(); }
555 template<typename Function, typename Functor>
556 bool
557 compare_equal(const Function& f, const Functor& g, long,
558 mpl::bool_<false>)
560 if (const Functor* fp = f.template target<Functor>())
561 return function_equal(*fp, g);
562 else return false;
565 template<typename Function, typename Functor>
566 bool
567 compare_equal(const Function& f, const reference_wrapper<Functor>& g,
568 int, mpl::bool_<false>)
570 if (const Functor* fp = f.template target<Functor>())
571 return fp == g.get_pointer();
572 else return false;
575 template<typename Function, typename Functor>
576 bool
577 compare_not_equal(const Function& f, const Functor& g, long,
578 mpl::bool_<false>)
580 if (const Functor* fp = f.template target<Functor>())
581 return !function_equal(*fp, g);
582 else return true;
585 template<typename Function, typename Functor>
586 bool
587 compare_not_equal(const Function& f,
588 const reference_wrapper<Functor>& g, int,
589 mpl::bool_<false>)
591 if (const Functor* fp = f.template target<Functor>())
592 return fp != g.get_pointer();
593 else return true;
595 #endif // BOOST_NO_SFINAE
598 * Stores the "manager" portion of the vtable for a
599 * boost::function object.
601 struct vtable_base
603 void (*manager)(const function_buffer& in_buffer,
604 function_buffer& out_buffer,
605 functor_manager_operation_type op);
607 } // end namespace function
608 } // end namespace detail
611 * The function_base class contains the basic elements needed for the
612 * function1, function2, function3, etc. classes. It is common to all
613 * functions (and as such can be used to tell if we have one of the
614 * functionN objects).
616 class function_base
618 public:
619 function_base() : vtable(0) { }
621 /** Determine if the function is empty (i.e., has no target). */
622 bool empty() const { return !vtable; }
624 /** Retrieve the type of the stored function object, or typeid(void)
625 if this is empty. */
626 const BOOST_FUNCTION_STD_NS::type_info& target_type() const
628 if (!vtable) return typeid(void);
630 detail::function::function_buffer type;
631 get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
632 return *type.type.type;
635 template<typename Functor>
636 Functor* target()
638 if (!vtable) return 0;
640 detail::function::function_buffer type_result;
641 type_result.type.type = &typeid(Functor);
642 type_result.type.const_qualified = is_const<Functor>::value;
643 type_result.type.volatile_qualified = is_volatile<Functor>::value;
644 get_vtable()->manager(functor, type_result,
645 detail::function::check_functor_type_tag);
646 return static_cast<Functor*>(type_result.obj_ptr);
649 template<typename Functor>
650 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
651 const Functor* target( Functor * = 0 ) const
652 #else
653 const Functor* target() const
654 #endif
656 if (!vtable) return 0;
658 detail::function::function_buffer type_result;
659 type_result.type.type = &typeid(Functor);
660 type_result.type.const_qualified = true;
661 type_result.type.volatile_qualified = is_volatile<Functor>::value;
662 get_vtable()->manager(functor, type_result,
663 detail::function::check_functor_type_tag);
664 // GCC 2.95.3 gets the CV qualifiers wrong here, so we
665 // can't do the static_cast that we should do.
666 return (const Functor*)(type_result.obj_ptr);
669 template<typename F>
670 bool contains(const F& f) const
672 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
673 if (const F* fp = this->target( (F*)0 ))
674 #else
675 if (const F* fp = this->template target<F>())
676 #endif
678 return function_equal(*fp, f);
679 } else {
680 return false;
684 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
685 // GCC 3.3 and newer cannot copy with the global operator==, due to
686 // problems with instantiation of function return types before it
687 // has been verified that the argument types match up.
688 template<typename Functor>
689 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
690 operator==(Functor g) const
692 if (const Functor* fp = target<Functor>())
693 return function_equal(*fp, g);
694 else return false;
697 template<typename Functor>
698 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
699 operator!=(Functor g) const
701 if (const Functor* fp = target<Functor>())
702 return !function_equal(*fp, g);
703 else return true;
705 #endif
707 public: // should be protected, but GCC 2.95.3 will fail to allow access
708 detail::function::vtable_base* get_vtable() const {
709 return reinterpret_cast<detail::function::vtable_base*>(
710 reinterpret_cast<std::size_t>(vtable) & ~(std::size_t)0x01);
713 bool has_trivial_copy_and_destroy() const {
714 return reinterpret_cast<std::size_t>(vtable) & 0x01;
717 detail::function::vtable_base* vtable;
718 mutable detail::function::function_buffer functor;
722 * The bad_function_call exception class is thrown when a boost::function
723 * object is invoked
725 class bad_function_call : public std::runtime_error
727 public:
728 bad_function_call() : std::runtime_error("call to empty boost::function") {}
731 #ifndef BOOST_NO_SFINAE
732 inline bool operator==(const function_base& f,
733 detail::function::useless_clear_type*)
735 return f.empty();
738 inline bool operator!=(const function_base& f,
739 detail::function::useless_clear_type*)
741 return !f.empty();
744 inline bool operator==(detail::function::useless_clear_type*,
745 const function_base& f)
747 return f.empty();
750 inline bool operator!=(detail::function::useless_clear_type*,
751 const function_base& f)
753 return !f.empty();
755 #endif
757 #ifdef BOOST_NO_SFINAE
758 // Comparisons between boost::function objects and arbitrary function objects
759 template<typename Functor>
760 inline bool operator==(const function_base& f, Functor g)
762 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
763 return detail::function::compare_equal(f, g, 0, integral());
766 template<typename Functor>
767 inline bool operator==(Functor g, const function_base& f)
769 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
770 return detail::function::compare_equal(f, g, 0, integral());
773 template<typename Functor>
774 inline bool operator!=(const function_base& f, Functor g)
776 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
777 return detail::function::compare_not_equal(f, g, 0, integral());
780 template<typename Functor>
781 inline bool operator!=(Functor g, const function_base& f)
783 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
784 return detail::function::compare_not_equal(f, g, 0, integral());
786 #else
788 # if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
789 // Comparisons between boost::function objects and arbitrary function
790 // objects. GCC 3.3 and before has an obnoxious bug that prevents this
791 // from working.
792 template<typename Functor>
793 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
794 operator==(const function_base& f, Functor g)
796 if (const Functor* fp = f.template target<Functor>())
797 return function_equal(*fp, g);
798 else return false;
801 template<typename Functor>
802 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
803 operator==(Functor g, const function_base& f)
805 if (const Functor* fp = f.template target<Functor>())
806 return function_equal(g, *fp);
807 else return false;
810 template<typename Functor>
811 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
812 operator!=(const function_base& f, Functor g)
814 if (const Functor* fp = f.template target<Functor>())
815 return !function_equal(*fp, g);
816 else return true;
819 template<typename Functor>
820 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
821 operator!=(Functor g, const function_base& f)
823 if (const Functor* fp = f.template target<Functor>())
824 return !function_equal(g, *fp);
825 else return true;
827 # endif
829 template<typename Functor>
830 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
831 operator==(const function_base& f, reference_wrapper<Functor> g)
833 if (const Functor* fp = f.template target<Functor>())
834 return fp == g.get_pointer();
835 else return false;
838 template<typename Functor>
839 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
840 operator==(reference_wrapper<Functor> g, const function_base& f)
842 if (const Functor* fp = f.template target<Functor>())
843 return g.get_pointer() == fp;
844 else return false;
847 template<typename Functor>
848 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
849 operator!=(const function_base& f, reference_wrapper<Functor> g)
851 if (const Functor* fp = f.template target<Functor>())
852 return fp != g.get_pointer();
853 else return true;
856 template<typename Functor>
857 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
858 operator!=(reference_wrapper<Functor> g, const function_base& f)
860 if (const Functor* fp = f.template target<Functor>())
861 return g.get_pointer() != fp;
862 else return true;
865 #endif // Compiler supporting SFINAE
867 namespace detail {
868 namespace function {
869 inline bool has_empty_target(const function_base* f)
871 return f->empty();
874 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
875 inline bool has_empty_target(const void*)
877 return false;
879 #else
880 inline bool has_empty_target(...)
882 return false;
884 #endif
885 } // end namespace function
886 } // end namespace detail
887 } // end namespace boost
889 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
890 #undef BOOST_FUNCTION_COMPARE_TYPE_ID
892 #endif // BOOST_FUNCTION_BASE_HEADER