File indexing completed on 2025-01-18 09:30:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_FUNCTION_BASE_HEADER
0012 #define BOOST_FUNCTION_BASE_HEADER
0013
0014 #include <boost/function/function_fwd.hpp>
0015 #include <boost/function_equal.hpp>
0016 #include <boost/core/typeinfo.hpp>
0017 #include <boost/core/ref.hpp>
0018 #include <boost/type_traits/has_trivial_copy.hpp>
0019 #include <boost/type_traits/has_trivial_destructor.hpp>
0020 #include <boost/type_traits/is_const.hpp>
0021 #include <boost/type_traits/is_integral.hpp>
0022 #include <boost/type_traits/is_volatile.hpp>
0023 #include <boost/type_traits/composite_traits.hpp>
0024 #include <boost/type_traits/conditional.hpp>
0025 #include <boost/type_traits/alignment_of.hpp>
0026 #include <boost/type_traits/enable_if.hpp>
0027 #include <boost/type_traits/integral_constant.hpp>
0028 #include <boost/type_traits/is_function.hpp>
0029 #include <boost/assert.hpp>
0030 #include <boost/config.hpp>
0031 #include <boost/config/workaround.hpp>
0032 #include <stdexcept>
0033 #include <string>
0034 #include <memory>
0035 #include <new>
0036
0037 #if defined(BOOST_MSVC)
0038 # pragma warning( push )
0039 # pragma warning( disable : 4793 )
0040 # pragma warning( disable : 4127 )
0041 #endif
0042
0043 #if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
0044 # define BOOST_FUNCTION_TARGET_FIX(x) x
0045 #else
0046 # define BOOST_FUNCTION_TARGET_FIX(x)
0047 #endif
0048
0049 # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
0050 typename ::boost::enable_if_< \
0051 !(::boost::is_integral<Functor>::value), \
0052 Type>::type
0053
0054 namespace boost {
0055 namespace detail {
0056 namespace function {
0057 class X;
0058
0059
0060
0061
0062
0063
0064
0065 union function_buffer_members
0066 {
0067
0068 typedef void* obj_ptr_t;
0069 mutable obj_ptr_t obj_ptr;
0070
0071
0072 struct type_t {
0073
0074 const boost::core::typeinfo* type;
0075
0076
0077 bool const_qualified;
0078
0079 bool volatile_qualified;
0080 } type;
0081
0082
0083 typedef void (*func_ptr_t)();
0084 mutable func_ptr_t func_ptr;
0085
0086 #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
0087 # pragma warning(push)
0088 # pragma warning(disable: 5243)
0089 #endif
0090
0091
0092 struct bound_memfunc_ptr_t {
0093 void (X::*memfunc_ptr)(int);
0094 void* obj_ptr;
0095 } bound_memfunc_ptr;
0096
0097 #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
0098 # pragma warning(pop)
0099 #endif
0100
0101
0102
0103 struct obj_ref_t {
0104 mutable void* obj_ptr;
0105 bool is_const_qualified;
0106 bool is_volatile_qualified;
0107 } obj_ref;
0108 };
0109
0110 union BOOST_SYMBOL_VISIBLE function_buffer
0111 {
0112
0113 mutable function_buffer_members members;
0114
0115
0116 mutable char data[sizeof(function_buffer_members)];
0117 };
0118
0119
0120
0121
0122
0123
0124
0125 struct unusable
0126 {
0127 unusable() {}
0128 template<typename T> unusable(const T&) {}
0129 };
0130
0131
0132
0133
0134
0135 template<typename T> struct function_return_type { typedef T type; };
0136
0137 template<>
0138 struct function_return_type<void>
0139 {
0140 typedef unusable type;
0141 };
0142
0143
0144 enum functor_manager_operation_type {
0145 clone_functor_tag,
0146 move_functor_tag,
0147 destroy_functor_tag,
0148 check_functor_type_tag,
0149 get_functor_type_tag
0150 };
0151
0152
0153 struct function_ptr_tag {};
0154 struct function_obj_tag {};
0155 struct member_ptr_tag {};
0156 struct function_obj_ref_tag {};
0157
0158 template<typename F>
0159 class get_function_tag
0160 {
0161 typedef typename conditional<(is_pointer<F>::value),
0162 function_ptr_tag,
0163 function_obj_tag>::type ptr_or_obj_tag;
0164
0165 typedef typename conditional<(is_member_pointer<F>::value),
0166 member_ptr_tag,
0167 ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
0168
0169 typedef typename conditional<(is_reference_wrapper<F>::value),
0170 function_obj_ref_tag,
0171 ptr_or_obj_or_mem_tag>::type or_ref_tag;
0172
0173 public:
0174 typedef or_ref_tag type;
0175 };
0176
0177
0178
0179 template<typename F>
0180 struct reference_manager
0181 {
0182 static inline void
0183 manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0184 functor_manager_operation_type op)
0185 {
0186 switch (op) {
0187 case clone_functor_tag:
0188 out_buffer.members.obj_ref = in_buffer.members.obj_ref;
0189 return;
0190
0191 case move_functor_tag:
0192 out_buffer.members.obj_ref = in_buffer.members.obj_ref;
0193 in_buffer.members.obj_ref.obj_ptr = 0;
0194 return;
0195
0196 case destroy_functor_tag:
0197 out_buffer.members.obj_ref.obj_ptr = 0;
0198 return;
0199
0200 case check_functor_type_tag:
0201 {
0202
0203
0204 if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(F)
0205 && (!in_buffer.members.obj_ref.is_const_qualified
0206 || out_buffer.members.type.const_qualified)
0207 && (!in_buffer.members.obj_ref.is_volatile_qualified
0208 || out_buffer.members.type.volatile_qualified))
0209 out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
0210 else
0211 out_buffer.members.obj_ptr = 0;
0212 }
0213 return;
0214
0215 case get_functor_type_tag:
0216 out_buffer.members.type.type = &BOOST_CORE_TYPEID(F);
0217 out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
0218 out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
0219 return;
0220 }
0221 }
0222 };
0223
0224
0225
0226
0227
0228 template<typename F>
0229 struct function_allows_small_object_optimization
0230 {
0231 BOOST_STATIC_CONSTANT
0232 (bool,
0233 value = ((sizeof(F) <= sizeof(function_buffer) &&
0234 (alignment_of<function_buffer>::value
0235 % alignment_of<F>::value == 0))));
0236 };
0237
0238 template <typename F,typename A>
0239 struct functor_wrapper: public F, public A
0240 {
0241 functor_wrapper( F f, A a ):
0242 F(f),
0243 A(a)
0244 {
0245 }
0246
0247 functor_wrapper(const functor_wrapper& f) :
0248 F(static_cast<const F&>(f)),
0249 A(static_cast<const A&>(f))
0250 {
0251 }
0252 };
0253
0254
0255
0256
0257
0258 template<typename Functor>
0259 struct functor_manager_common
0260 {
0261 typedef Functor functor_type;
0262
0263
0264 static inline void
0265 manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
0266 functor_manager_operation_type op)
0267 {
0268 if (op == clone_functor_tag)
0269 out_buffer.members.func_ptr = in_buffer.members.func_ptr;
0270 else if (op == move_functor_tag) {
0271 out_buffer.members.func_ptr = in_buffer.members.func_ptr;
0272 in_buffer.members.func_ptr = 0;
0273 } else if (op == destroy_functor_tag)
0274 out_buffer.members.func_ptr = 0;
0275 else if (op == check_functor_type_tag) {
0276 if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0277 out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
0278 else
0279 out_buffer.members.obj_ptr = 0;
0280 } else {
0281 out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0282 out_buffer.members.type.const_qualified = false;
0283 out_buffer.members.type.volatile_qualified = false;
0284 }
0285 }
0286
0287
0288 static inline void
0289 manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
0290 functor_manager_operation_type op)
0291 {
0292 if (op == clone_functor_tag || op == move_functor_tag) {
0293 const functor_type* in_functor =
0294 reinterpret_cast<const functor_type*>(in_buffer.data);
0295 new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
0296
0297 if (op == move_functor_tag) {
0298 functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
0299 (void)f;
0300 f->~Functor();
0301 }
0302 } else if (op == destroy_functor_tag) {
0303
0304 functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data);
0305 (void)f;
0306 f->~Functor();
0307 } else if (op == check_functor_type_tag) {
0308 if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0309 out_buffer.members.obj_ptr = in_buffer.data;
0310 else
0311 out_buffer.members.obj_ptr = 0;
0312 } else {
0313 out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0314 out_buffer.members.type.const_qualified = false;
0315 out_buffer.members.type.volatile_qualified = false;
0316 }
0317 }
0318 };
0319
0320 template<typename Functor>
0321 struct functor_manager
0322 {
0323 private:
0324 typedef Functor functor_type;
0325
0326
0327 static inline void
0328 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0329 functor_manager_operation_type op, function_ptr_tag)
0330 {
0331 functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
0332 }
0333
0334
0335 static inline void
0336 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0337 functor_manager_operation_type op, true_type)
0338 {
0339 functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
0340 }
0341
0342
0343 static inline void
0344 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0345 functor_manager_operation_type op, false_type)
0346 {
0347 if (op == clone_functor_tag) {
0348
0349
0350
0351
0352
0353 const functor_type* f =
0354 static_cast<const functor_type*>(in_buffer.members.obj_ptr);
0355 functor_type* new_f = new functor_type(*f);
0356 out_buffer.members.obj_ptr = new_f;
0357 } else if (op == move_functor_tag) {
0358 out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0359 in_buffer.members.obj_ptr = 0;
0360 } else if (op == destroy_functor_tag) {
0361
0362 functor_type* f =
0363 static_cast<functor_type*>(out_buffer.members.obj_ptr);
0364 delete f;
0365 out_buffer.members.obj_ptr = 0;
0366 } else if (op == check_functor_type_tag) {
0367 if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0368 out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0369 else
0370 out_buffer.members.obj_ptr = 0;
0371 } else {
0372 out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0373 out_buffer.members.type.const_qualified = false;
0374 out_buffer.members.type.volatile_qualified = false;
0375 }
0376 }
0377
0378
0379
0380
0381 static inline void
0382 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0383 functor_manager_operation_type op, function_obj_tag)
0384 {
0385 manager(in_buffer, out_buffer, op,
0386 integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
0387 }
0388
0389
0390 static inline void
0391 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0392 functor_manager_operation_type op, member_ptr_tag)
0393 {
0394 manager(in_buffer, out_buffer, op, true_type());
0395 }
0396
0397 public:
0398
0399
0400 static inline void
0401 manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0402 functor_manager_operation_type op)
0403 {
0404 typedef typename get_function_tag<functor_type>::type tag_type;
0405 if (op == get_functor_type_tag) {
0406 out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
0407 out_buffer.members.type.const_qualified = false;
0408 out_buffer.members.type.volatile_qualified = false;
0409 } else {
0410 manager(in_buffer, out_buffer, op, tag_type());
0411 }
0412 }
0413 };
0414
0415 template<typename Functor, typename Allocator>
0416 struct functor_manager_a
0417 {
0418 private:
0419 typedef Functor functor_type;
0420
0421
0422 static inline void
0423 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0424 functor_manager_operation_type op, function_ptr_tag)
0425 {
0426 functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
0427 }
0428
0429
0430 static inline void
0431 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0432 functor_manager_operation_type op, true_type)
0433 {
0434 functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
0435 }
0436
0437
0438 static inline void
0439 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0440 functor_manager_operation_type op, false_type)
0441 {
0442 typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
0443 #if defined(BOOST_NO_CXX11_ALLOCATOR)
0444 typedef typename Allocator::template rebind<functor_wrapper_type>::other
0445 wrapper_allocator_type;
0446 typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
0447 #else
0448 using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
0449 using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
0450 #endif
0451
0452 if (op == clone_functor_tag) {
0453
0454
0455
0456 const functor_wrapper_type* f =
0457 static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
0458 wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
0459 wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
0460 #if defined(BOOST_NO_CXX11_ALLOCATOR)
0461 wrapper_allocator.construct(copy, *f);
0462 #else
0463 std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, *f);
0464 #endif
0465
0466
0467 functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
0468 out_buffer.members.obj_ptr = new_f;
0469 } else if (op == move_functor_tag) {
0470 out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0471 in_buffer.members.obj_ptr = 0;
0472 } else if (op == destroy_functor_tag) {
0473
0474 functor_wrapper_type* victim =
0475 static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
0476 wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
0477 #if defined(BOOST_NO_CXX11_ALLOCATOR)
0478 wrapper_allocator.destroy(victim);
0479 #else
0480 std::allocator_traits<wrapper_allocator_type>::destroy(wrapper_allocator, victim);
0481 #endif
0482 wrapper_allocator.deallocate(victim,1);
0483 out_buffer.members.obj_ptr = 0;
0484 } else if (op == check_functor_type_tag) {
0485 if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0486 out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0487 else
0488 out_buffer.members.obj_ptr = 0;
0489 } else {
0490 out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0491 out_buffer.members.type.const_qualified = false;
0492 out_buffer.members.type.volatile_qualified = false;
0493 }
0494 }
0495
0496
0497
0498
0499 static inline void
0500 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0501 functor_manager_operation_type op, function_obj_tag)
0502 {
0503 manager(in_buffer, out_buffer, op,
0504 integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
0505 }
0506
0507 public:
0508
0509
0510 static inline void
0511 manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0512 functor_manager_operation_type op)
0513 {
0514 typedef typename get_function_tag<functor_type>::type tag_type;
0515 if (op == get_functor_type_tag) {
0516 out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
0517 out_buffer.members.type.const_qualified = false;
0518 out_buffer.members.type.volatile_qualified = false;
0519 } else {
0520 manager(in_buffer, out_buffer, op, tag_type());
0521 }
0522 }
0523 };
0524
0525
0526 struct useless_clear_type {};
0527
0528 #ifdef BOOST_NO_SFINAE
0529
0530
0531
0532
0533
0534 template<typename Function, typename Functor>
0535 bool
0536 compare_equal(const Function& f, const Functor&, int, true_type)
0537 { return f.empty(); }
0538
0539 template<typename Function, typename Functor>
0540 bool
0541 compare_not_equal(const Function& f, const Functor&, int,
0542 true_type)
0543 { return !f.empty(); }
0544
0545 template<typename Function, typename Functor>
0546 bool
0547 compare_equal(const Function& f, const Functor& g, long,
0548 false_type)
0549 {
0550 if (const Functor* fp = f.template target<Functor>())
0551 return function_equal(*fp, g);
0552 else return false;
0553 }
0554
0555 template<typename Function, typename Functor>
0556 bool
0557 compare_equal(const Function& f, const reference_wrapper<Functor>& g,
0558 int, false_type)
0559 {
0560 if (const Functor* fp = f.template target<Functor>())
0561 return fp == g.get_pointer();
0562 else return false;
0563 }
0564
0565 template<typename Function, typename Functor>
0566 bool
0567 compare_not_equal(const Function& f, const Functor& g, long,
0568 false_type)
0569 {
0570 if (const Functor* fp = f.template target<Functor>())
0571 return !function_equal(*fp, g);
0572 else return true;
0573 }
0574
0575 template<typename Function, typename Functor>
0576 bool
0577 compare_not_equal(const Function& f,
0578 const reference_wrapper<Functor>& g, int,
0579 false_type)
0580 {
0581 if (const Functor* fp = f.template target<Functor>())
0582 return fp != g.get_pointer();
0583 else return true;
0584 }
0585 #endif
0586
0587
0588
0589
0590
0591 struct vtable_base
0592 {
0593 void (*manager)(const function_buffer& in_buffer,
0594 function_buffer& out_buffer,
0595 functor_manager_operation_type op);
0596 };
0597 }
0598 }
0599
0600
0601
0602
0603
0604
0605
0606 class function_base
0607 {
0608 public:
0609 function_base() : vtable(0) { }
0610
0611
0612 bool empty() const { return !vtable; }
0613
0614
0615
0616 const boost::core::typeinfo& target_type() const
0617 {
0618 if (!vtable) return BOOST_CORE_TYPEID(void);
0619
0620 detail::function::function_buffer type;
0621 get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
0622 return *type.members.type.type;
0623 }
0624
0625 template<typename Functor>
0626 Functor* target()
0627 {
0628 if (!vtable) return 0;
0629
0630 detail::function::function_buffer type_result;
0631 type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
0632 type_result.members.type.const_qualified = is_const<Functor>::value;
0633 type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
0634 get_vtable()->manager(functor, type_result,
0635 detail::function::check_functor_type_tag);
0636 return static_cast<Functor*>(type_result.members.obj_ptr);
0637 }
0638
0639 template<typename Functor>
0640 const Functor* target() const
0641 {
0642 if (!vtable) return 0;
0643
0644 detail::function::function_buffer type_result;
0645 type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
0646 type_result.members.type.const_qualified = true;
0647 type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
0648 get_vtable()->manager(functor, type_result,
0649 detail::function::check_functor_type_tag);
0650
0651
0652 return static_cast<const Functor*>(type_result.members.obj_ptr);
0653 }
0654
0655 template<typename F>
0656 typename boost::enable_if_< !boost::is_function<F>::value, bool >::type
0657 contains(const F& f) const
0658 {
0659 if (const F* fp = this->template target<F>())
0660 {
0661 return function_equal(*fp, f);
0662 } else {
0663 return false;
0664 }
0665 }
0666
0667 template<typename Fn>
0668 typename boost::enable_if_< boost::is_function<Fn>::value, bool >::type
0669 contains(Fn& f) const
0670 {
0671 typedef Fn* F;
0672 if (const F* fp = this->template target<F>())
0673 {
0674 return function_equal(*fp, &f);
0675 } else {
0676 return false;
0677 }
0678 }
0679
0680 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
0681
0682
0683
0684 template<typename Functor>
0685 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0686 operator==(Functor g) const
0687 {
0688 if (const Functor* fp = target<Functor>())
0689 return function_equal(*fp, g);
0690 else return false;
0691 }
0692
0693 template<typename Functor>
0694 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0695 operator!=(Functor g) const
0696 {
0697 if (const Functor* fp = target<Functor>())
0698 return !function_equal(*fp, g);
0699 else return true;
0700 }
0701 #endif
0702
0703 public:
0704 detail::function::vtable_base* get_vtable() const {
0705 return reinterpret_cast<detail::function::vtable_base*>(
0706 reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
0707 }
0708
0709 bool has_trivial_copy_and_destroy() const {
0710 return reinterpret_cast<std::size_t>(vtable) & 0x01;
0711 }
0712
0713 detail::function::vtable_base* vtable;
0714 mutable detail::function::function_buffer functor;
0715 };
0716
0717 #if defined(BOOST_CLANG)
0718 # pragma clang diagnostic push
0719 # pragma clang diagnostic ignored "-Wweak-vtables"
0720 #endif
0721
0722
0723
0724
0725 class BOOST_SYMBOL_VISIBLE bad_function_call : public std::runtime_error
0726 {
0727 public:
0728 bad_function_call() : std::runtime_error("call to empty boost::function") {}
0729 };
0730 #if defined(BOOST_CLANG)
0731 # pragma clang diagnostic pop
0732 #endif
0733
0734 #ifndef BOOST_NO_SFINAE
0735 inline bool operator==(const function_base& f,
0736 detail::function::useless_clear_type*)
0737 {
0738 return f.empty();
0739 }
0740
0741 inline bool operator!=(const function_base& f,
0742 detail::function::useless_clear_type*)
0743 {
0744 return !f.empty();
0745 }
0746
0747 inline bool operator==(detail::function::useless_clear_type*,
0748 const function_base& f)
0749 {
0750 return f.empty();
0751 }
0752
0753 inline bool operator!=(detail::function::useless_clear_type*,
0754 const function_base& f)
0755 {
0756 return !f.empty();
0757 }
0758 #endif
0759
0760 #ifdef BOOST_NO_SFINAE
0761
0762 template<typename Functor>
0763 inline bool operator==(const function_base& f, Functor g)
0764 {
0765 typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
0766 return detail::function::compare_equal(f, g, 0, integral());
0767 }
0768
0769 template<typename Functor>
0770 inline bool operator==(Functor g, const function_base& f)
0771 {
0772 typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
0773 return detail::function::compare_equal(f, g, 0, integral());
0774 }
0775
0776 template<typename Functor>
0777 inline bool operator!=(const function_base& f, Functor g)
0778 {
0779 typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
0780 return detail::function::compare_not_equal(f, g, 0, integral());
0781 }
0782
0783 template<typename Functor>
0784 inline bool operator!=(Functor g, const function_base& f)
0785 {
0786 typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
0787 return detail::function::compare_not_equal(f, g, 0, integral());
0788 }
0789 #else
0790
0791 # if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
0792
0793
0794
0795 template<typename Functor>
0796 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0797 operator==(const function_base& f, Functor g)
0798 {
0799 if (const Functor* fp = f.template target<Functor>())
0800 return function_equal(*fp, g);
0801 else return false;
0802 }
0803
0804 template<typename Functor>
0805 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0806 operator==(Functor g, const function_base& f)
0807 {
0808 if (const Functor* fp = f.template target<Functor>())
0809 return function_equal(g, *fp);
0810 else return false;
0811 }
0812
0813 template<typename Functor>
0814 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0815 operator!=(const function_base& f, Functor g)
0816 {
0817 if (const Functor* fp = f.template target<Functor>())
0818 return !function_equal(*fp, g);
0819 else return true;
0820 }
0821
0822 template<typename Functor>
0823 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0824 operator!=(Functor g, const function_base& f)
0825 {
0826 if (const Functor* fp = f.template target<Functor>())
0827 return !function_equal(g, *fp);
0828 else return true;
0829 }
0830 # endif
0831
0832 template<typename Functor>
0833 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0834 operator==(const function_base& f, reference_wrapper<Functor> g)
0835 {
0836 if (const Functor* fp = f.template target<Functor>())
0837 return fp == g.get_pointer();
0838 else return false;
0839 }
0840
0841 template<typename Functor>
0842 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0843 operator==(reference_wrapper<Functor> g, const function_base& f)
0844 {
0845 if (const Functor* fp = f.template target<Functor>())
0846 return g.get_pointer() == fp;
0847 else return false;
0848 }
0849
0850 template<typename Functor>
0851 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0852 operator!=(const function_base& f, reference_wrapper<Functor> g)
0853 {
0854 if (const Functor* fp = f.template target<Functor>())
0855 return fp != g.get_pointer();
0856 else return true;
0857 }
0858
0859 template<typename Functor>
0860 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0861 operator!=(reference_wrapper<Functor> g, const function_base& f)
0862 {
0863 if (const Functor* fp = f.template target<Functor>())
0864 return g.get_pointer() != fp;
0865 else return true;
0866 }
0867
0868 #endif
0869
0870 namespace detail {
0871 namespace function {
0872 inline bool has_empty_target(const function_base* f)
0873 {
0874 return f->empty();
0875 }
0876
0877 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
0878 inline bool has_empty_target(const void*)
0879 {
0880 return false;
0881 }
0882 #else
0883 inline bool has_empty_target(...)
0884 {
0885 return false;
0886 }
0887 #endif
0888 }
0889 }
0890 }
0891
0892 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
0893
0894 #if defined(BOOST_MSVC)
0895 # pragma warning( pop )
0896 #endif
0897
0898 #endif