File indexing completed on 2025-07-11 08:07:11
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/assert.hpp>
0019 #include <boost/config.hpp>
0020 #include <boost/config/workaround.hpp>
0021 #include <stdexcept>
0022 #include <string>
0023 #include <memory>
0024 #include <new>
0025 #include <type_traits>
0026
0027 #if defined(BOOST_MSVC)
0028 # pragma warning( push )
0029 # pragma warning( disable : 4793 )
0030 # pragma warning( disable : 4127 )
0031 #endif
0032
0033
0034 #define BOOST_FUNCTION_TARGET_FIX(x)
0035
0036 #define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
0037 typename std::enable_if< !std::is_integral<Functor>::value, Type>::type
0038
0039 namespace boost {
0040 namespace detail {
0041 namespace function {
0042 class X;
0043
0044
0045
0046
0047
0048
0049
0050 union function_buffer_members
0051 {
0052
0053 typedef void* obj_ptr_t;
0054 mutable obj_ptr_t obj_ptr;
0055
0056
0057 struct type_t {
0058
0059 const boost::core::typeinfo* type;
0060
0061
0062 bool const_qualified;
0063
0064 bool volatile_qualified;
0065 } type;
0066
0067
0068 typedef void (*func_ptr_t)();
0069 mutable func_ptr_t func_ptr;
0070
0071 #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
0072 # pragma warning(push)
0073 # pragma warning(disable: 5243)
0074 #endif
0075
0076
0077 struct bound_memfunc_ptr_t {
0078 void (X::*memfunc_ptr)(int);
0079 void* obj_ptr;
0080 } bound_memfunc_ptr;
0081
0082 #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
0083 # pragma warning(pop)
0084 #endif
0085
0086
0087
0088 struct obj_ref_t {
0089 mutable void* obj_ptr;
0090 bool is_const_qualified;
0091 bool is_volatile_qualified;
0092 } obj_ref;
0093 };
0094
0095 union BOOST_SYMBOL_VISIBLE function_buffer
0096 {
0097
0098 mutable function_buffer_members members;
0099
0100
0101 mutable char data[sizeof(function_buffer_members)];
0102 };
0103
0104
0105 enum functor_manager_operation_type {
0106 clone_functor_tag,
0107 move_functor_tag,
0108 destroy_functor_tag,
0109 check_functor_type_tag,
0110 get_functor_type_tag
0111 };
0112
0113
0114 struct function_ptr_tag {};
0115 struct function_obj_tag {};
0116 struct member_ptr_tag {};
0117 struct function_obj_ref_tag {};
0118
0119 template<typename F>
0120 class get_function_tag
0121 {
0122 typedef typename std::conditional<std::is_pointer<F>::value,
0123 function_ptr_tag,
0124 function_obj_tag>::type ptr_or_obj_tag;
0125
0126 typedef typename std::conditional<std::is_member_pointer<F>::value,
0127 member_ptr_tag,
0128 ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
0129
0130 typedef typename std::conditional<is_reference_wrapper<F>::value,
0131 function_obj_ref_tag,
0132 ptr_or_obj_or_mem_tag>::type or_ref_tag;
0133
0134 public:
0135 typedef or_ref_tag type;
0136 };
0137
0138
0139
0140 template<typename F>
0141 struct reference_manager
0142 {
0143 static inline void
0144 manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0145 functor_manager_operation_type op)
0146 {
0147 switch (op) {
0148 case clone_functor_tag:
0149 out_buffer.members.obj_ref = in_buffer.members.obj_ref;
0150 return;
0151
0152 case move_functor_tag:
0153 out_buffer.members.obj_ref = in_buffer.members.obj_ref;
0154 in_buffer.members.obj_ref.obj_ptr = 0;
0155 return;
0156
0157 case destroy_functor_tag:
0158 out_buffer.members.obj_ref.obj_ptr = 0;
0159 return;
0160
0161 case check_functor_type_tag:
0162 {
0163
0164
0165 if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(F)
0166 && (!in_buffer.members.obj_ref.is_const_qualified
0167 || out_buffer.members.type.const_qualified)
0168 && (!in_buffer.members.obj_ref.is_volatile_qualified
0169 || out_buffer.members.type.volatile_qualified))
0170 out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
0171 else
0172 out_buffer.members.obj_ptr = 0;
0173 }
0174 return;
0175
0176 case get_functor_type_tag:
0177 out_buffer.members.type.type = &BOOST_CORE_TYPEID(F);
0178 out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
0179 out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
0180 return;
0181 }
0182 }
0183 };
0184
0185
0186
0187
0188
0189 template<typename F>
0190 struct function_allows_small_object_optimization
0191 {
0192 BOOST_STATIC_CONSTANT
0193 (bool,
0194 value = ((sizeof(F) <= sizeof(function_buffer) &&
0195 (std::alignment_of<function_buffer>::value
0196 % std::alignment_of<F>::value == 0))));
0197 };
0198
0199 template <typename F,typename A>
0200 struct functor_wrapper: public F, public A
0201 {
0202 functor_wrapper( F f, A a ):
0203 F(f),
0204 A(a)
0205 {
0206 }
0207
0208 functor_wrapper(const functor_wrapper& f) :
0209 F(static_cast<const F&>(f)),
0210 A(static_cast<const A&>(f))
0211 {
0212 }
0213 };
0214
0215
0216
0217
0218
0219 template<typename Functor>
0220 struct functor_manager_common
0221 {
0222 typedef Functor functor_type;
0223
0224
0225 static inline void
0226 manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
0227 functor_manager_operation_type op)
0228 {
0229 if (op == clone_functor_tag)
0230 out_buffer.members.func_ptr = in_buffer.members.func_ptr;
0231 else if (op == move_functor_tag) {
0232 out_buffer.members.func_ptr = in_buffer.members.func_ptr;
0233 in_buffer.members.func_ptr = 0;
0234 } else if (op == destroy_functor_tag)
0235 out_buffer.members.func_ptr = 0;
0236 else if (op == check_functor_type_tag) {
0237 if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0238 out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
0239 else
0240 out_buffer.members.obj_ptr = 0;
0241 } else {
0242 out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0243 out_buffer.members.type.const_qualified = false;
0244 out_buffer.members.type.volatile_qualified = false;
0245 }
0246 }
0247
0248
0249 static inline void
0250 manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
0251 functor_manager_operation_type op)
0252 {
0253 if (op == clone_functor_tag) {
0254 const functor_type* in_functor =
0255 reinterpret_cast<const functor_type*>(in_buffer.data);
0256 new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
0257
0258 } else if (op == move_functor_tag) {
0259 functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
0260 new (reinterpret_cast<void*>(out_buffer.data)) functor_type(std::move(*f));
0261 f->~Functor();
0262 } else if (op == destroy_functor_tag) {
0263
0264 functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data);
0265 (void)f;
0266 f->~Functor();
0267 } else if (op == check_functor_type_tag) {
0268 if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0269 out_buffer.members.obj_ptr = in_buffer.data;
0270 else
0271 out_buffer.members.obj_ptr = 0;
0272 } else {
0273 out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0274 out_buffer.members.type.const_qualified = false;
0275 out_buffer.members.type.volatile_qualified = false;
0276 }
0277 }
0278 };
0279
0280 template<typename Functor>
0281 struct functor_manager
0282 {
0283 private:
0284 typedef Functor functor_type;
0285
0286
0287 static inline void
0288 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0289 functor_manager_operation_type op, function_ptr_tag)
0290 {
0291 functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
0292 }
0293
0294
0295 static inline void
0296 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0297 functor_manager_operation_type op, std::true_type)
0298 {
0299 functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
0300 }
0301
0302
0303 static inline void
0304 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0305 functor_manager_operation_type op, std::false_type)
0306 {
0307 if (op == clone_functor_tag) {
0308
0309
0310
0311
0312
0313 const functor_type* f =
0314 static_cast<const functor_type*>(in_buffer.members.obj_ptr);
0315 functor_type* new_f = new functor_type(*f);
0316 out_buffer.members.obj_ptr = new_f;
0317 } else if (op == move_functor_tag) {
0318 out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0319 in_buffer.members.obj_ptr = 0;
0320 } else if (op == destroy_functor_tag) {
0321
0322 functor_type* f =
0323 static_cast<functor_type*>(out_buffer.members.obj_ptr);
0324 delete f;
0325 out_buffer.members.obj_ptr = 0;
0326 } else if (op == check_functor_type_tag) {
0327 if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0328 out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0329 else
0330 out_buffer.members.obj_ptr = 0;
0331 } else {
0332 out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0333 out_buffer.members.type.const_qualified = false;
0334 out_buffer.members.type.volatile_qualified = false;
0335 }
0336 }
0337
0338
0339
0340
0341 static inline void
0342 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0343 functor_manager_operation_type op, function_obj_tag)
0344 {
0345 manager(in_buffer, out_buffer, op,
0346 std::integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
0347 }
0348
0349
0350 static inline void
0351 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0352 functor_manager_operation_type op, member_ptr_tag)
0353 {
0354 manager(in_buffer, out_buffer, op, std::true_type());
0355 }
0356
0357 public:
0358
0359
0360 static inline void
0361 manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0362 functor_manager_operation_type op)
0363 {
0364 typedef typename get_function_tag<functor_type>::type tag_type;
0365 if (op == get_functor_type_tag) {
0366 out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
0367 out_buffer.members.type.const_qualified = false;
0368 out_buffer.members.type.volatile_qualified = false;
0369 } else {
0370 manager(in_buffer, out_buffer, op, tag_type());
0371 }
0372 }
0373 };
0374
0375 template<typename Functor, typename Allocator>
0376 struct functor_manager_a
0377 {
0378 private:
0379 typedef Functor functor_type;
0380
0381
0382 static inline void
0383 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0384 functor_manager_operation_type op, function_ptr_tag)
0385 {
0386 functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
0387 }
0388
0389
0390 static inline void
0391 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0392 functor_manager_operation_type op, std::true_type)
0393 {
0394 functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
0395 }
0396
0397
0398 static inline void
0399 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0400 functor_manager_operation_type op, std::false_type)
0401 {
0402 typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
0403
0404 using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
0405 using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
0406
0407 if (op == clone_functor_tag) {
0408
0409
0410
0411 const functor_wrapper_type* f =
0412 static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
0413 wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
0414 wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
0415 std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, *f);
0416
0417
0418 functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
0419 out_buffer.members.obj_ptr = new_f;
0420 } else if (op == move_functor_tag) {
0421 out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0422 in_buffer.members.obj_ptr = 0;
0423 } else if (op == destroy_functor_tag) {
0424
0425 functor_wrapper_type* victim =
0426 static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
0427 wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
0428 std::allocator_traits<wrapper_allocator_type>::destroy(wrapper_allocator, victim);
0429 wrapper_allocator.deallocate(victim,1);
0430 out_buffer.members.obj_ptr = 0;
0431 } else if (op == check_functor_type_tag) {
0432 if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0433 out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0434 else
0435 out_buffer.members.obj_ptr = 0;
0436 } else {
0437 out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0438 out_buffer.members.type.const_qualified = false;
0439 out_buffer.members.type.volatile_qualified = false;
0440 }
0441 }
0442
0443
0444
0445
0446 static inline void
0447 manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0448 functor_manager_operation_type op, function_obj_tag)
0449 {
0450 manager(in_buffer, out_buffer, op,
0451 std::integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
0452 }
0453
0454 public:
0455
0456
0457 static inline void
0458 manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0459 functor_manager_operation_type op)
0460 {
0461 typedef typename get_function_tag<functor_type>::type tag_type;
0462 if (op == get_functor_type_tag) {
0463 out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
0464 out_buffer.members.type.const_qualified = false;
0465 out_buffer.members.type.volatile_qualified = false;
0466 } else {
0467 manager(in_buffer, out_buffer, op, tag_type());
0468 }
0469 }
0470 };
0471
0472
0473 struct useless_clear_type {};
0474
0475
0476
0477
0478
0479 struct vtable_base
0480 {
0481 void (*manager)(const function_buffer& in_buffer,
0482 function_buffer& out_buffer,
0483 functor_manager_operation_type op);
0484 };
0485 }
0486 }
0487
0488
0489
0490
0491
0492
0493
0494 class function_base
0495 {
0496 public:
0497 function_base() : vtable(0) { }
0498
0499
0500 bool empty() const { return !vtable; }
0501
0502
0503
0504 const boost::core::typeinfo& target_type() const
0505 {
0506 if (!vtable) return BOOST_CORE_TYPEID(void);
0507
0508 detail::function::function_buffer type;
0509 get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
0510 return *type.members.type.type;
0511 }
0512
0513 template<typename Functor>
0514 Functor* target()
0515 {
0516 if (!vtable) return 0;
0517
0518 detail::function::function_buffer type_result;
0519 type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
0520 type_result.members.type.const_qualified = std::is_const<Functor>::value;
0521 type_result.members.type.volatile_qualified = std::is_volatile<Functor>::value;
0522 get_vtable()->manager(functor, type_result,
0523 detail::function::check_functor_type_tag);
0524 return static_cast<Functor*>(type_result.members.obj_ptr);
0525 }
0526
0527 template<typename Functor>
0528 const Functor* target() const
0529 {
0530 if (!vtable) return 0;
0531
0532 detail::function::function_buffer type_result;
0533 type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
0534 type_result.members.type.const_qualified = true;
0535 type_result.members.type.volatile_qualified = std::is_volatile<Functor>::value;
0536 get_vtable()->manager(functor, type_result,
0537 detail::function::check_functor_type_tag);
0538
0539
0540 return static_cast<const Functor*>(type_result.members.obj_ptr);
0541 }
0542
0543 template<typename F>
0544 typename std::enable_if< !std::is_function<F>::value, bool >::type
0545 contains(const F& f) const
0546 {
0547 if (const F* fp = this->template target<F>())
0548 {
0549 return function_equal(*fp, f);
0550 } else {
0551 return false;
0552 }
0553 }
0554
0555 template<typename Fn>
0556 typename std::enable_if< std::is_function<Fn>::value, bool >::type
0557 contains(Fn& f) const
0558 {
0559 typedef Fn* F;
0560 if (const F* fp = this->template target<F>())
0561 {
0562 return function_equal(*fp, &f);
0563 } else {
0564 return false;
0565 }
0566 }
0567
0568 public:
0569 detail::function::vtable_base* get_vtable() const {
0570 return reinterpret_cast<detail::function::vtable_base*>(
0571 reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
0572 }
0573
0574 bool has_trivial_copy_and_destroy() const {
0575 return reinterpret_cast<std::size_t>(vtable) & 0x01;
0576 }
0577
0578 detail::function::vtable_base* vtable;
0579 mutable detail::function::function_buffer functor;
0580 };
0581
0582 #if defined(BOOST_CLANG)
0583 # pragma clang diagnostic push
0584 # pragma clang diagnostic ignored "-Wweak-vtables"
0585 #endif
0586
0587
0588
0589
0590 class BOOST_SYMBOL_VISIBLE bad_function_call : public std::runtime_error
0591 {
0592 public:
0593 bad_function_call() : std::runtime_error("call to empty boost::function") {}
0594 };
0595 #if defined(BOOST_CLANG)
0596 # pragma clang diagnostic pop
0597 #endif
0598
0599 inline bool operator==(const function_base& f,
0600 detail::function::useless_clear_type*)
0601 {
0602 return f.empty();
0603 }
0604
0605 inline bool operator!=(const function_base& f,
0606 detail::function::useless_clear_type*)
0607 {
0608 return !f.empty();
0609 }
0610
0611 inline bool operator==(detail::function::useless_clear_type*,
0612 const function_base& f)
0613 {
0614 return f.empty();
0615 }
0616
0617 inline bool operator!=(detail::function::useless_clear_type*,
0618 const function_base& f)
0619 {
0620 return !f.empty();
0621 }
0622
0623
0624
0625
0626 template<typename Functor>
0627 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0628 operator==(const function_base& f, Functor g)
0629 {
0630 if (const Functor* fp = f.template target<Functor>())
0631 return function_equal(*fp, g);
0632 else return false;
0633 }
0634
0635 template<typename Functor>
0636 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0637 operator==(Functor g, const function_base& f)
0638 {
0639 if (const Functor* fp = f.template target<Functor>())
0640 return function_equal(g, *fp);
0641 else return false;
0642 }
0643
0644 template<typename Functor>
0645 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0646 operator!=(const function_base& f, Functor g)
0647 {
0648 if (const Functor* fp = f.template target<Functor>())
0649 return !function_equal(*fp, g);
0650 else return true;
0651 }
0652
0653 template<typename Functor>
0654 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0655 operator!=(Functor g, const function_base& f)
0656 {
0657 if (const Functor* fp = f.template target<Functor>())
0658 return !function_equal(g, *fp);
0659 else return true;
0660 }
0661
0662 template<typename Functor>
0663 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0664 operator==(const function_base& f, reference_wrapper<Functor> g)
0665 {
0666 if (const Functor* fp = f.template target<Functor>())
0667 return fp == g.get_pointer();
0668 else return false;
0669 }
0670
0671 template<typename Functor>
0672 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0673 operator==(reference_wrapper<Functor> g, const function_base& f)
0674 {
0675 if (const Functor* fp = f.template target<Functor>())
0676 return g.get_pointer() == fp;
0677 else return false;
0678 }
0679
0680 template<typename Functor>
0681 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0682 operator!=(const function_base& f, reference_wrapper<Functor> g)
0683 {
0684 if (const Functor* fp = f.template target<Functor>())
0685 return fp != g.get_pointer();
0686 else return true;
0687 }
0688
0689 template<typename Functor>
0690 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0691 operator!=(reference_wrapper<Functor> g, const function_base& f)
0692 {
0693 if (const Functor* fp = f.template target<Functor>())
0694 return g.get_pointer() != fp;
0695 else return true;
0696 }
0697
0698 namespace detail {
0699 namespace function {
0700 inline bool has_empty_target(const function_base* f)
0701 {
0702 return f->empty();
0703 }
0704
0705 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
0706 inline bool has_empty_target(const void*)
0707 {
0708 return false;
0709 }
0710 #else
0711 inline bool has_empty_target(...)
0712 {
0713 return false;
0714 }
0715 #endif
0716 }
0717 }
0718 }
0719
0720 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
0721
0722 #if defined(BOOST_MSVC)
0723 # pragma warning( pop )
0724 #endif
0725
0726 #endif