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
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"
36 # include "boost/mpl/bool.hpp"
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"
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
52 # define BOOST_FUNCTION_STD_NS std
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) \
59 || ( defined(__sgi) && defined(__host_mips))
61 # define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
62 (std::strcmp((X).name(),(Y).name()) == 0)
64 # define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
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
70 # define BOOST_FUNCTION_TARGET_FIX(x)
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), \
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), \
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.
100 // For pointers to function objects
101 mutable void* obj_ptr
;
103 // For pointers to std::type_info objects
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
;
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);
123 // For references to function objects. We explicitly keep
124 // track of the cv-qualifiers on the object referenced.
126 mutable void* obj_ptr
;
127 bool is_const_qualified
;
128 bool is_volatile_qualified
;
131 // To relax aliasing constraints
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.
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
; };
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
{
164 check_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
{};
175 class get_function_tag
177 typedef typename
mpl::if_c
<(is_pointer
<F
>::value
),
179 function_obj_tag
>::type ptr_or_obj_tag
;
181 typedef typename
mpl::if_c
<(is_member_pointer
<F
>::value
),
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
;
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).
196 struct reference_manager
199 manage(const function_buffer
& in_buffer
, function_buffer
& out_buffer
,
200 functor_manager_operation_type op
)
203 case clone_functor_tag
:
204 out_buffer
.obj_ref
.obj_ptr
= in_buffer
.obj_ref
.obj_ptr
;
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;
212 case destroy_functor_tag
:
213 out_buffer
.obj_ref
.obj_ptr
= 0;
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
;
230 out_buffer
.obj_ptr
= 0;
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
;
244 * Determine if boost::function can use the small-object
245 * optimization with the function object type F.
248 struct function_allows_small_object_optimization
250 BOOST_STATIC_CONSTANT
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
):
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
;
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
;
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.
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
;
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
337 typedef Functor functor_type
;
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.
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
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
) {
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 */
374 static_cast<functor_type
*>(out_buffer
.obj_ptr
);
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
;
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.
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.
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_());
411 /* Dispatch to an appropriate manager based on whether we have a
412 function pointer or a function object pointer. */
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
;
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;
426 manager(in_buffer
, out_buffer
, op
, tag_type());
432 template<typename Functor
, typename Allocator
>
433 struct functor_manager_a
436 typedef Functor functor_type
;
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.
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
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
) {
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
;
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.
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
)>());
514 /* Dispatch to an appropriate manager based on whether we have a
515 function pointer or a function object pointer. */
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
;
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;
529 manager(in_buffer
, out_buffer
, op
, tag_type());
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
>
546 compare_equal(const Function
& f
, const Functor
&, int, mpl::bool_
<true>)
547 { return f
.empty(); }
549 template<typename Function
, typename Functor
>
551 compare_not_equal(const Function
& f
, const Functor
&, int,
553 { return !f
.empty(); }
555 template<typename Function
, typename Functor
>
557 compare_equal(const Function
& f
, const Functor
& g
, long,
560 if (const Functor
* fp
= f
.template target
<Functor
>())
561 return function_equal(*fp
, g
);
565 template<typename Function
, typename Functor
>
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();
575 template<typename Function
, typename Functor
>
577 compare_not_equal(const Function
& f
, const Functor
& g
, long,
580 if (const Functor
* fp
= f
.template target
<Functor
>())
581 return !function_equal(*fp
, g
);
585 template<typename Function
, typename Functor
>
587 compare_not_equal(const Function
& f
,
588 const reference_wrapper
<Functor
>& g
, int,
591 if (const Functor
* fp
= f
.template target
<Functor
>())
592 return fp
!= g
.get_pointer();
595 #endif // BOOST_NO_SFINAE
598 * Stores the "manager" portion of the vtable for a
599 * boost::function object.
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).
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)
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
>
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
653 const Functor
* target() const
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
);
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 ))
675 if (const F
* fp
= this->template target
<F
>())
678 return function_equal(*fp
, f
);
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
);
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
);
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
725 class bad_function_call
: public std::runtime_error
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
*)
738 inline bool operator!=(const function_base
& f
,
739 detail::function::useless_clear_type
*)
744 inline bool operator==(detail::function::useless_clear_type
*,
745 const function_base
& f
)
750 inline bool operator!=(detail::function::useless_clear_type
*,
751 const function_base
& f
)
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());
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
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
);
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
);
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
);
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
);
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();
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
;
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();
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
;
865 #endif // Compiler supporting SFINAE
869 inline bool has_empty_target(const function_base
* f
)
874 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
875 inline bool has_empty_target(const void*)
880 inline bool has_empty_target(...)
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