Warning, file /include/boost/function/function_template.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 #ifndef BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP_INCLUDED
0002 #define BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <boost/function/function_base.hpp>
0015 #include <boost/core/no_exceptions_support.hpp>
0016 #include <boost/mem_fn.hpp>
0017 #include <boost/throw_exception.hpp>
0018 #include <boost/config.hpp>
0019 #include <algorithm>
0020 #include <cassert>
0021 #include <type_traits>
0022
0023 #if defined(BOOST_MSVC)
0024 # pragma warning( push )
0025 # pragma warning( disable : 4127 )
0026 #endif
0027
0028 namespace boost {
0029 namespace detail {
0030 namespace function {
0031 template<
0032 typename FunctionPtr,
0033 typename R,
0034 typename... T
0035 >
0036 struct function_invoker
0037 {
0038 static R invoke(function_buffer& function_ptr,
0039 T... a)
0040 {
0041 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
0042 return f(static_cast<T&&>(a)...);
0043 }
0044 };
0045
0046 template<
0047 typename FunctionPtr,
0048 typename R,
0049 typename... T
0050 >
0051 struct void_function_invoker
0052 {
0053 static void
0054 invoke(function_buffer& function_ptr,
0055 T... a)
0056
0057 {
0058 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
0059 f(static_cast<T&&>(a)...);
0060 }
0061 };
0062
0063 template<
0064 typename FunctionObj,
0065 typename R,
0066 typename... T
0067 >
0068 struct function_obj_invoker
0069 {
0070 static R invoke(function_buffer& function_obj_ptr,
0071 T... a)
0072
0073 {
0074 FunctionObj* f;
0075 if (function_allows_small_object_optimization<FunctionObj>::value)
0076 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
0077 else
0078 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
0079 return (*f)(static_cast<T&&>(a)...);
0080 }
0081 };
0082
0083 template<
0084 typename FunctionObj,
0085 typename R,
0086 typename... T
0087 >
0088 struct void_function_obj_invoker
0089 {
0090 static void
0091 invoke(function_buffer& function_obj_ptr,
0092 T... a)
0093
0094 {
0095 FunctionObj* f;
0096 if (function_allows_small_object_optimization<FunctionObj>::value)
0097 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
0098 else
0099 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
0100 (*f)(static_cast<T&&>(a)...);
0101 }
0102 };
0103
0104 template<
0105 typename FunctionObj,
0106 typename R,
0107 typename... T
0108 >
0109 struct function_ref_invoker
0110 {
0111 static R invoke(function_buffer& function_obj_ptr,
0112 T... a)
0113
0114 {
0115 FunctionObj* f =
0116 reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
0117 return (*f)(static_cast<T&&>(a)...);
0118 }
0119 };
0120
0121 template<
0122 typename FunctionObj,
0123 typename R,
0124 typename... T
0125 >
0126 struct void_function_ref_invoker
0127 {
0128 static void
0129 invoke(function_buffer& function_obj_ptr,
0130 T... a)
0131
0132 {
0133 FunctionObj* f =
0134 reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
0135 (*f)(static_cast<T&&>(a)...);
0136 }
0137 };
0138
0139
0140 template<
0141 typename MemberPtr,
0142 typename R,
0143 typename... T
0144 >
0145 struct member_invoker
0146 {
0147 static R invoke(function_buffer& function_obj_ptr,
0148 T... a)
0149
0150 {
0151 MemberPtr* f =
0152 reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
0153 return boost::mem_fn(*f)(static_cast<T&&>(a)...);
0154 }
0155 };
0156
0157 template<
0158 typename MemberPtr,
0159 typename R,
0160 typename... T
0161 >
0162 struct void_member_invoker
0163 {
0164 static void
0165 invoke(function_buffer& function_obj_ptr,
0166 T... a)
0167
0168 {
0169 MemberPtr* f =
0170 reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
0171 boost::mem_fn(*f)(static_cast<T&&>(a)...);
0172 }
0173 };
0174
0175 template<
0176 typename FunctionPtr,
0177 typename R,
0178 typename... T
0179 >
0180 struct get_function_invoker
0181 {
0182 typedef typename std::conditional<std::is_void<R>::value,
0183 void_function_invoker<
0184 FunctionPtr,
0185 R,
0186 T...
0187 >,
0188 function_invoker<
0189 FunctionPtr,
0190 R,
0191 T...
0192 >
0193 >::type type;
0194 };
0195
0196 template<
0197 typename FunctionObj,
0198 typename R,
0199 typename... T
0200 >
0201 struct get_function_obj_invoker
0202 {
0203 typedef typename std::conditional<std::is_void<R>::value,
0204 void_function_obj_invoker<
0205 FunctionObj,
0206 R,
0207 T...
0208 >,
0209 function_obj_invoker<
0210 FunctionObj,
0211 R,
0212 T...
0213 >
0214 >::type type;
0215 };
0216
0217 template<
0218 typename FunctionObj,
0219 typename R,
0220 typename... T
0221 >
0222 struct get_function_ref_invoker
0223 {
0224 typedef typename std::conditional<std::is_void<R>::value,
0225 void_function_ref_invoker<
0226 FunctionObj,
0227 R,
0228 T...
0229 >,
0230 function_ref_invoker<
0231 FunctionObj,
0232 R,
0233 T...
0234 >
0235 >::type type;
0236 };
0237
0238
0239 template<
0240 typename MemberPtr,
0241 typename R,
0242 typename... T
0243 >
0244 struct get_member_invoker
0245 {
0246 typedef typename std::conditional<std::is_void<R>::value,
0247 void_member_invoker<
0248 MemberPtr,
0249 R,
0250 T...
0251 >,
0252 member_invoker<
0253 MemberPtr,
0254 R,
0255 T...
0256 >
0257 >::type type;
0258 };
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269 template<typename Tag>
0270 struct get_invoker { };
0271
0272
0273 template<>
0274 struct get_invoker<function_ptr_tag>
0275 {
0276 template<typename FunctionPtr,
0277 typename R, typename... T>
0278 struct apply
0279 {
0280 typedef typename get_function_invoker<
0281 FunctionPtr,
0282 R,
0283 T...
0284 >::type
0285 invoker_type;
0286
0287 typedef functor_manager<FunctionPtr> manager_type;
0288 };
0289
0290 template<typename FunctionPtr, typename Allocator,
0291 typename R, typename... T>
0292 struct apply_a
0293 {
0294 typedef typename get_function_invoker<
0295 FunctionPtr,
0296 R,
0297 T...
0298 >::type
0299 invoker_type;
0300
0301 typedef functor_manager<FunctionPtr> manager_type;
0302 };
0303 };
0304
0305
0306 template<>
0307 struct get_invoker<member_ptr_tag>
0308 {
0309 template<typename MemberPtr,
0310 typename R, typename... T>
0311 struct apply
0312 {
0313 typedef typename get_member_invoker<
0314 MemberPtr,
0315 R,
0316 T...
0317 >::type
0318 invoker_type;
0319
0320 typedef functor_manager<MemberPtr> manager_type;
0321 };
0322
0323 template<typename MemberPtr, typename Allocator,
0324 typename R, typename... T>
0325 struct apply_a
0326 {
0327 typedef typename get_member_invoker<
0328 MemberPtr,
0329 R,
0330 T...
0331 >::type
0332 invoker_type;
0333
0334 typedef functor_manager<MemberPtr> manager_type;
0335 };
0336 };
0337
0338
0339 template<>
0340 struct get_invoker<function_obj_tag>
0341 {
0342 template<typename FunctionObj,
0343 typename R, typename... T>
0344 struct apply
0345 {
0346 typedef typename get_function_obj_invoker<
0347 FunctionObj,
0348 R,
0349 T...
0350 >::type
0351 invoker_type;
0352
0353 typedef functor_manager<FunctionObj> manager_type;
0354 };
0355
0356 template<typename FunctionObj, typename Allocator,
0357 typename R, typename... T>
0358 struct apply_a
0359 {
0360 typedef typename get_function_obj_invoker<
0361 FunctionObj,
0362 R,
0363 T...
0364 >::type
0365 invoker_type;
0366
0367 typedef functor_manager_a<FunctionObj, Allocator> manager_type;
0368 };
0369 };
0370
0371
0372 template<>
0373 struct get_invoker<function_obj_ref_tag>
0374 {
0375 template<typename RefWrapper,
0376 typename R, typename... T>
0377 struct apply
0378 {
0379 typedef typename get_function_ref_invoker<
0380 typename RefWrapper::type,
0381 R,
0382 T...
0383 >::type
0384 invoker_type;
0385
0386 typedef reference_manager<typename RefWrapper::type> manager_type;
0387 };
0388
0389 template<typename RefWrapper, typename Allocator,
0390 typename R, typename... T>
0391 struct apply_a
0392 {
0393 typedef typename get_function_ref_invoker<
0394 typename RefWrapper::type,
0395 R,
0396 T...
0397 >::type
0398 invoker_type;
0399
0400 typedef reference_manager<typename RefWrapper::type> manager_type;
0401 };
0402 };
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412 template<typename R, typename... T>
0413 struct basic_vtable
0414 {
0415 typedef R result_type;
0416
0417 typedef result_type (*invoker_type)(function_buffer&
0418 ,
0419 T...);
0420
0421 template<typename F>
0422 bool assign_to(F f, function_buffer& functor) const
0423 {
0424 typedef typename get_function_tag<F>::type tag;
0425 return assign_to(std::move(f), functor, tag());
0426 }
0427 template<typename F,typename Allocator>
0428 bool assign_to_a(F f, function_buffer& functor, Allocator a) const
0429 {
0430 typedef typename get_function_tag<F>::type tag;
0431 return assign_to_a(std::move(f), functor, a, tag());
0432 }
0433
0434 void clear(function_buffer& functor) const
0435 {
0436 #if defined(BOOST_GCC) && (__GNUC__ >= 11)
0437 # pragma GCC diagnostic push
0438
0439 # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0440 #endif
0441 if (base.manager)
0442 base.manager(functor, functor, destroy_functor_tag);
0443 #if defined(BOOST_GCC) && (__GNUC__ >= 11)
0444 # pragma GCC diagnostic pop
0445 #endif
0446 }
0447
0448 private:
0449
0450 template<typename FunctionPtr>
0451 bool
0452 assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
0453 {
0454 this->clear(functor);
0455 if (f) {
0456 functor.members.func_ptr = reinterpret_cast<void (*)()>(f);
0457 return true;
0458 } else {
0459 return false;
0460 }
0461 }
0462 template<typename FunctionPtr,typename Allocator>
0463 bool
0464 assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
0465 {
0466 return assign_to(std::move(f),functor,function_ptr_tag());
0467 }
0468
0469
0470 template<typename MemberPtr>
0471 bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
0472 {
0473
0474
0475
0476 if (f) {
0477 this->assign_to(boost::mem_fn(f), functor);
0478 return true;
0479 } else {
0480 return false;
0481 }
0482 }
0483 template<typename MemberPtr,typename Allocator>
0484 bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const
0485 {
0486
0487
0488
0489 if (f) {
0490 this->assign_to_a(boost::mem_fn(f), functor, a);
0491 return true;
0492 } else {
0493 return false;
0494 }
0495 }
0496
0497
0498
0499 template<typename FunctionObj>
0500 void
0501 assign_functor(FunctionObj f, function_buffer& functor, std::true_type) const
0502 {
0503 new (reinterpret_cast<void*>(functor.data)) FunctionObj(std::move(f));
0504 }
0505 template<typename FunctionObj,typename Allocator>
0506 void
0507 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, std::true_type) const
0508 {
0509 assign_functor(std::move(f),functor,std::true_type());
0510 }
0511
0512
0513 template<typename FunctionObj>
0514 void
0515 assign_functor(FunctionObj f, function_buffer& functor, std::false_type) const
0516 {
0517 functor.members.obj_ptr = new FunctionObj(std::move(f));
0518 }
0519 template<typename FunctionObj,typename Allocator>
0520 void
0521 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, std::false_type) const
0522 {
0523 typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
0524
0525 using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
0526 using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
0527
0528 wrapper_allocator_type wrapper_allocator(a);
0529 wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
0530 std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, functor_wrapper_type(f,a));
0531
0532 functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
0533 functor.members.obj_ptr = new_f;
0534 }
0535
0536 template<typename FunctionObj>
0537 bool
0538 assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
0539 {
0540 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
0541 assign_functor(std::move(f), functor,
0542 std::integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>());
0543 return true;
0544 } else {
0545 return false;
0546 }
0547 }
0548 template<typename FunctionObj,typename Allocator>
0549 bool
0550 assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
0551 {
0552 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
0553 assign_functor_a(std::move(f), functor, a,
0554 std::integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>());
0555 return true;
0556 } else {
0557 return false;
0558 }
0559 }
0560
0561
0562 template<typename FunctionObj>
0563 bool
0564 assign_to(const reference_wrapper<FunctionObj>& f,
0565 function_buffer& functor, function_obj_ref_tag) const
0566 {
0567 functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer());
0568 functor.members.obj_ref.is_const_qualified = std::is_const<FunctionObj>::value;
0569 functor.members.obj_ref.is_volatile_qualified = std::is_volatile<FunctionObj>::value;
0570 return true;
0571 }
0572 template<typename FunctionObj,typename Allocator>
0573 bool
0574 assign_to_a(const reference_wrapper<FunctionObj>& f,
0575 function_buffer& functor, Allocator, function_obj_ref_tag) const
0576 {
0577 return assign_to(f,functor,function_obj_ref_tag());
0578 }
0579
0580 public:
0581 vtable_base base;
0582 invoker_type invoker;
0583 };
0584
0585 template <typename... T>
0586 struct variadic_function_base
0587 {};
0588
0589 template <typename T1>
0590 struct variadic_function_base<T1>
0591 {
0592 typedef T1 argument_type;
0593 typedef T1 arg1_type;
0594 };
0595
0596 template <typename T1, typename T2>
0597 struct variadic_function_base<T1, T2>
0598 {
0599 typedef T1 first_argument_type;
0600 typedef T2 second_argument_type;
0601 typedef T1 arg1_type;
0602 typedef T2 arg2_type;
0603 };
0604
0605 template <typename T1, typename T2, typename T3>
0606 struct variadic_function_base<T1, T2, T3>
0607 {
0608 typedef T1 arg1_type;
0609 typedef T2 arg2_type;
0610 typedef T3 arg3_type;
0611 };
0612
0613 template <typename T1, typename T2, typename T3, typename T4>
0614 struct variadic_function_base<T1, T2, T3, T4>
0615 {
0616 typedef T1 arg1_type;
0617 typedef T2 arg2_type;
0618 typedef T3 arg3_type;
0619 typedef T4 arg4_type;
0620 };
0621
0622 template <typename T1, typename T2, typename T3, typename T4, typename T5>
0623 struct variadic_function_base<T1, T2, T3, T4, T5>
0624 {
0625 typedef T1 arg1_type;
0626 typedef T2 arg2_type;
0627 typedef T3 arg3_type;
0628 typedef T4 arg4_type;
0629 typedef T5 arg5_type;
0630 };
0631
0632 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
0633 struct variadic_function_base<T1, T2, T3, T4, T5, T6>
0634 {
0635 typedef T1 arg1_type;
0636 typedef T2 arg2_type;
0637 typedef T3 arg3_type;
0638 typedef T4 arg4_type;
0639 typedef T5 arg5_type;
0640 typedef T6 arg6_type;
0641 };
0642
0643 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
0644 struct variadic_function_base<T1, T2, T3, T4, T5, T6, T7>
0645 {
0646 typedef T1 arg1_type;
0647 typedef T2 arg2_type;
0648 typedef T3 arg3_type;
0649 typedef T4 arg4_type;
0650 typedef T5 arg5_type;
0651 typedef T6 arg6_type;
0652 typedef T7 arg7_type;
0653 };
0654
0655 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
0656 struct variadic_function_base<T1, T2, T3, T4, T5, T6, T7, T8>
0657 {
0658 typedef T1 arg1_type;
0659 typedef T2 arg2_type;
0660 typedef T3 arg3_type;
0661 typedef T4 arg4_type;
0662 typedef T5 arg5_type;
0663 typedef T6 arg6_type;
0664 typedef T7 arg7_type;
0665 typedef T8 arg8_type;
0666 };
0667
0668 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
0669 struct variadic_function_base<T1, T2, T3, T4, T5, T6, T7, T8, T9>
0670 {
0671 typedef T1 arg1_type;
0672 typedef T2 arg2_type;
0673 typedef T3 arg3_type;
0674 typedef T4 arg4_type;
0675 typedef T5 arg5_type;
0676 typedef T6 arg6_type;
0677 typedef T7 arg7_type;
0678 typedef T8 arg8_type;
0679 typedef T9 arg9_type;
0680 };
0681
0682 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
0683 struct variadic_function_base<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
0684 {
0685 typedef T1 arg1_type;
0686 typedef T2 arg2_type;
0687 typedef T3 arg3_type;
0688 typedef T4 arg4_type;
0689 typedef T5 arg5_type;
0690 typedef T6 arg6_type;
0691 typedef T7 arg7_type;
0692 typedef T8 arg8_type;
0693 typedef T9 arg9_type;
0694 typedef T10 arg10_type;
0695 };
0696
0697 #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000
0698
0699 template<class T> struct is_trivially_copyable: std::integral_constant<bool,
0700 __has_trivial_copy(T) && __has_trivial_assign(T) && __has_trivial_destructor(T)> {};
0701
0702 #else
0703
0704 using std::is_trivially_copyable;
0705
0706 #endif
0707
0708 }
0709 }
0710
0711 template<
0712 typename R,
0713 typename... T
0714 >
0715 class function_n : public function_base
0716 , public detail::function::variadic_function_base<T...>
0717 {
0718 public:
0719 typedef R result_type;
0720
0721 private:
0722 typedef boost::detail::function::basic_vtable<
0723 R, T...>
0724 vtable_type;
0725
0726 vtable_type* get_vtable() const {
0727 return reinterpret_cast<vtable_type*>(
0728 reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
0729 }
0730
0731 struct clear_type {};
0732
0733 public:
0734
0735 template<typename Args>
0736 struct sig
0737 {
0738 typedef result_type type;
0739 };
0740
0741 BOOST_STATIC_CONSTANT(int, arity = sizeof...(T));
0742
0743 typedef function_n self_type;
0744
0745 BOOST_DEFAULTED_FUNCTION(function_n(), : function_base() {})
0746
0747
0748
0749 template<typename Functor>
0750 function_n(Functor f
0751 ,typename std::enable_if<
0752 !std::is_integral<Functor>::value,
0753 int>::type = 0
0754 ) :
0755 function_base()
0756 {
0757 this->assign_to(std::move(f));
0758 }
0759 template<typename Functor,typename Allocator>
0760 function_n(Functor f, Allocator a
0761 ,typename std::enable_if<
0762 !std::is_integral<Functor>::value,
0763 int>::type = 0
0764 ) :
0765 function_base()
0766 {
0767 this->assign_to_a(std::move(f),a);
0768 }
0769
0770 function_n(clear_type*) : function_base() { }
0771
0772 function_n(const function_n& f) : function_base()
0773 {
0774 this->assign_to_own(f);
0775 }
0776
0777 function_n(function_n&& f) : function_base()
0778 {
0779 this->move_assign(f);
0780 }
0781
0782 ~function_n() { clear(); }
0783
0784 result_type operator()(T... a) const
0785 {
0786 if (this->empty())
0787 boost::throw_exception(bad_function_call());
0788
0789 return get_vtable()->invoker
0790 (this->functor, static_cast<T&&>(a)...);
0791 }
0792
0793
0794
0795
0796
0797
0798 template<typename Functor>
0799 typename std::enable_if<
0800 !std::is_integral<Functor>::value,
0801 function_n&>::type
0802 operator=(Functor f)
0803 {
0804 this->clear();
0805 BOOST_TRY {
0806 this->assign_to(f);
0807 } BOOST_CATCH (...) {
0808 vtable = 0;
0809 BOOST_RETHROW;
0810 }
0811 BOOST_CATCH_END
0812 return *this;
0813 }
0814 template<typename Functor,typename Allocator>
0815 void assign(Functor f, Allocator a)
0816 {
0817 this->clear();
0818 BOOST_TRY{
0819 this->assign_to_a(f,a);
0820 } BOOST_CATCH (...) {
0821 vtable = 0;
0822 BOOST_RETHROW;
0823 }
0824 BOOST_CATCH_END
0825 }
0826
0827 function_n& operator=(clear_type*)
0828 {
0829 this->clear();
0830 return *this;
0831 }
0832
0833
0834 function_n& operator=(const function_n& f)
0835 {
0836 if (&f == this)
0837 return *this;
0838
0839 this->clear();
0840 BOOST_TRY {
0841 this->assign_to_own(f);
0842 } BOOST_CATCH (...) {
0843 vtable = 0;
0844 BOOST_RETHROW;
0845 }
0846 BOOST_CATCH_END
0847 return *this;
0848 }
0849
0850
0851 function_n& operator=(function_n&& f)
0852 {
0853 if (&f == this)
0854 return *this;
0855
0856 this->clear();
0857 BOOST_TRY {
0858 this->move_assign(f);
0859 } BOOST_CATCH (...) {
0860 vtable = 0;
0861 BOOST_RETHROW;
0862 }
0863 BOOST_CATCH_END
0864 return *this;
0865 }
0866
0867 void swap(function_n& other)
0868 {
0869 if (&other == this)
0870 return;
0871
0872 function_n tmp;
0873 tmp.move_assign(*this);
0874 this->move_assign(other);
0875 other.move_assign(tmp);
0876 }
0877
0878
0879 void clear()
0880 {
0881 if (vtable) {
0882 if (!this->has_trivial_copy_and_destroy())
0883 get_vtable()->clear(this->functor);
0884 vtable = 0;
0885 }
0886 }
0887
0888 explicit operator bool () const { return !this->empty(); }
0889
0890 private:
0891 void assign_to_own(const function_n& f)
0892 {
0893 if (!f.empty()) {
0894 this->vtable = f.vtable;
0895 if (this->has_trivial_copy_and_destroy()) {
0896
0897
0898 # if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
0899 # pragma GCC diagnostic push
0900
0901
0902 # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0903 # if (BOOST_GCC >= 110000)
0904
0905 # pragma GCC diagnostic ignored "-Wuninitialized"
0906 # endif
0907 # endif
0908 std::memcpy(this->functor.data, f.functor.data, sizeof(boost::detail::function::function_buffer));
0909 # if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
0910 # pragma GCC diagnostic pop
0911 # endif
0912 } else
0913 get_vtable()->base.manager(f.functor, this->functor,
0914 boost::detail::function::clone_functor_tag);
0915 }
0916 }
0917
0918 template<typename Functor>
0919 void assign_to(Functor f)
0920 {
0921 using boost::detail::function::vtable_base;
0922
0923 typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
0924 typedef boost::detail::function::get_invoker<tag> get_invoker;
0925 typedef typename get_invoker::
0926 template apply<Functor, R,
0927 T...>
0928 handler_type;
0929
0930 typedef typename handler_type::invoker_type invoker_type;
0931 typedef typename handler_type::manager_type manager_type;
0932
0933
0934
0935
0936
0937 static const vtable_type stored_vtable =
0938 { { &manager_type::manage }, &invoker_type::invoke };
0939
0940 if (stored_vtable.assign_to(std::move(f), functor)) {
0941 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
0942
0943 if (boost::detail::function::is_trivially_copyable<Functor>::value &&
0944 boost::detail::function::function_allows_small_object_optimization<Functor>::value)
0945 value |= static_cast<std::size_t>(0x01);
0946 vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
0947 } else
0948 vtable = 0;
0949 }
0950
0951 template<typename Functor,typename Allocator>
0952 void assign_to_a(Functor f,Allocator a)
0953 {
0954 using boost::detail::function::vtable_base;
0955
0956 typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
0957 typedef boost::detail::function::get_invoker<tag> get_invoker;
0958 typedef typename get_invoker::
0959 template apply_a<Functor, Allocator, R,
0960 T...>
0961 handler_type;
0962
0963 typedef typename handler_type::invoker_type invoker_type;
0964 typedef typename handler_type::manager_type manager_type;
0965
0966
0967
0968
0969
0970 static const vtable_type stored_vtable =
0971 { { &manager_type::manage }, &invoker_type::invoke };
0972
0973 if (stored_vtable.assign_to_a(std::move(f), functor, a)) {
0974 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
0975
0976 if (boost::detail::function::is_trivially_copyable<Functor>::value &&
0977 boost::detail::function::function_allows_small_object_optimization<Functor>::value)
0978 value |= static_cast<std::size_t>(0x01);
0979 vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
0980 } else
0981 vtable = 0;
0982 }
0983
0984
0985
0986
0987 void move_assign(function_n& f)
0988 {
0989 if (&f == this)
0990 return;
0991
0992 BOOST_TRY {
0993 if (!f.empty()) {
0994 this->vtable = f.vtable;
0995 if (this->has_trivial_copy_and_destroy()) {
0996
0997
0998 # if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
0999 # pragma GCC diagnostic push
1000
1001
1002 # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1003 # if (BOOST_GCC >= 120000)
1004
1005 # pragma GCC diagnostic ignored "-Wuninitialized"
1006 # endif
1007 # endif
1008 std::memcpy(this->functor.data, f.functor.data, sizeof(this->functor.data));
1009 # if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
1010 # pragma GCC diagnostic pop
1011 # endif
1012 } else
1013 #if defined(BOOST_GCC) && (__GNUC__ >= 11)
1014 # pragma GCC diagnostic push
1015
1016 # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1017 #endif
1018 get_vtable()->base.manager(f.functor, this->functor,
1019 boost::detail::function::move_functor_tag);
1020 #if defined(BOOST_GCC) && (__GNUC__ >= 11)
1021 # pragma GCC diagnostic pop
1022 #endif
1023 f.vtable = 0;
1024 } else {
1025 clear();
1026 }
1027 } BOOST_CATCH (...) {
1028 vtable = 0;
1029 BOOST_RETHROW;
1030 }
1031 BOOST_CATCH_END
1032 }
1033 };
1034
1035 template<typename R, typename... T>
1036 inline void swap(function_n<
1037 R,
1038 T...
1039 >& f1,
1040 function_n<
1041 R,
1042 T...
1043 >& f2)
1044 {
1045 f1.swap(f2);
1046 }
1047
1048
1049 template<typename R, typename... T>
1050 void operator==(const function_n<
1051 R,
1052 T...>&,
1053 const function_n<
1054 R,
1055 T...>&);
1056 template<typename R, typename... T>
1057 void operator!=(const function_n<
1058 R,
1059 T...>&,
1060 const function_n<
1061 R,
1062 T...>& );
1063
1064 template<typename R,
1065 typename... T>
1066 class function<R (T...)>
1067 : public function_n<R, T...>
1068 {
1069 typedef function_n<R, T...> base_type;
1070 typedef function self_type;
1071
1072 struct clear_type {};
1073
1074 public:
1075
1076 BOOST_DEFAULTED_FUNCTION(function(), : base_type() {})
1077
1078 template<typename Functor>
1079 function(Functor f
1080 ,typename std::enable_if<
1081 !std::is_integral<Functor>::value,
1082 int>::type = 0
1083 ) :
1084 base_type(std::move(f))
1085 {
1086 }
1087 template<typename Functor,typename Allocator>
1088 function(Functor f, Allocator a
1089 ,typename std::enable_if<
1090 !std::is_integral<Functor>::value,
1091 int>::type = 0
1092 ) :
1093 base_type(std::move(f),a)
1094 {
1095 }
1096
1097 function(clear_type*) : base_type() {}
1098
1099 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1100
1101 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1102
1103
1104 function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
1105 function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
1106
1107 self_type& operator=(const self_type& f)
1108 {
1109 self_type(f).swap(*this);
1110 return *this;
1111 }
1112
1113 self_type& operator=(self_type&& f)
1114 {
1115 self_type(static_cast<self_type&&>(f)).swap(*this);
1116 return *this;
1117 }
1118
1119 template<typename Functor>
1120 typename std::enable_if<
1121 !std::is_integral<Functor>::value,
1122 self_type&>::type
1123 operator=(Functor f)
1124 {
1125 self_type(f).swap(*this);
1126 return *this;
1127 }
1128
1129 self_type& operator=(clear_type*)
1130 {
1131 this->clear();
1132 return *this;
1133 }
1134
1135 self_type& operator=(const base_type& f)
1136 {
1137 self_type(f).swap(*this);
1138 return *this;
1139 }
1140
1141 self_type& operator=(base_type&& f)
1142 {
1143 self_type(static_cast<base_type&&>(f)).swap(*this);
1144 return *this;
1145 }
1146 };
1147
1148 }
1149
1150 #if defined(BOOST_MSVC)
1151 # pragma warning( pop )
1152 #endif
1153
1154
1155
1156
1157 namespace boost
1158 {
1159
1160 namespace _bi
1161 {
1162
1163 template<class R, class F, class L> class bind_t;
1164
1165 }
1166
1167 template<class S, class R, class F, class L> bool operator==( function<S> const& f, _bi::bind_t<R, F, L> const& b )
1168 {
1169 return f.contains( b );
1170 }
1171
1172 template<class S, class R, class F, class L> bool operator!=( function<S> const& f, _bi::bind_t<R, F, L> const& b )
1173 {
1174 return !f.contains( b );
1175 }
1176
1177 }
1178
1179 #endif