Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:37:46

0001 #ifndef BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP_INCLUDED
0002 #define BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP_INCLUDED
0003 
0004 // Boost.Function library
0005 
0006 //  Copyright Douglas Gregor 2001-2006
0007 //  Copyright Emil Dotchevski 2007
0008 //  Use, modification and distribution is subject to the Boost Software License, Version 1.0.
0009 //  (See accompanying file LICENSE_1_0.txt or copy at
0010 //  http://www.boost.org/LICENSE_1_0.txt)
0011 
0012 // For more information, see http://www.boost.org
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 ) // "conditional expression is constant"
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       /* Handle invocation of member pointers. */
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       /* Retrieve the appropriate invoker for a member pointer.  */
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       /* Given the tag returned by get_function_tag, retrieve the
0261          actual invoker that will be used for the given function
0262          object.
0263 
0264          Each specialization contains an "apply_" nested class template
0265          that accepts the function object, return type, function
0266          argument types, and allocator. The resulting "apply_" class
0267          contains two typedefs, "invoker_type" and "manager_type",
0268          which correspond to the invoker and manager types. */
0269       template<typename Tag>
0270       struct get_invoker { };
0271 
0272       /* Retrieve the invoker for a function pointer. */
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       /* Retrieve the invoker for a member pointer. */
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       /* Retrieve the invoker for a function object. */
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       /* Retrieve the invoker for a reference to a function object. */
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        * vtable for a specific boost::function instance. This
0407        * structure must be an aggregate so that we can use static
0408        * initialization in boost::function's assign_to and assign_to_a
0409        * members. It therefore cannot have any constructors,
0410        * destructors, base classes, etc.
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 // False positive in GCC 11/12 for empty function objects
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         // Function pointers
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         // Member pointers
0470         template<typename MemberPtr>
0471         bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
0472         {
0473           // DPG TBD: Add explicit support for member function
0474           // objects, so we invoke through mem_fn() but we retain the
0475           // right target_type() values.
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           // DPG TBD: Add explicit support for member function
0487           // objects, so we invoke through mem_fn() but we retain the
0488           // right target_type() values.
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         // Function objects
0498         // Assign to a function object using the small object optimization
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         // Assign to a function object allocated on the heap.
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         // Reference to a function object
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     } // end namespace function
0709   } // end namespace detail
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     // add signature for boost::lambda
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     // MSVC chokes if the following two constructors are collapsed into
0748     // one with a default parameter.
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     // The distinction between when to use function_n and
0794     // when to use self_type is obnoxious. MSVC cannot handle self_type as
0795     // the return type of these assignment operators, but Borland C++ cannot
0796     // handle function_n as the type of the temporary to
0797     // construct.
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     // Assignment from another function_n
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     // Move assignment from another function_n
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     // Clear out a target, if there is one
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           // Don't operate on storage directly since union type doesn't relax
0897           // strict aliasing rules, despite of having member char type.
0898 #         if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
0899 #           pragma GCC diagnostic push
0900             // This warning is technically correct, but we don't want to pay the price for initializing
0901             // just to silence a warning: https://github.com/boostorg/function/issues/27
0902 #           pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0903 #           if (BOOST_GCC >= 110000)
0904               // GCC 11.3, 12 emit a different warning: https://github.com/boostorg/function/issues/42
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       // Note: it is extremely important that this initialization use
0934       // static initialization. Otherwise, we will have a race
0935       // condition here in multi-threaded code. See
0936       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
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         // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
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       // Note: it is extremely important that this initialization use
0967       // static initialization. Otherwise, we will have a race
0968       // condition here in multi-threaded code. See
0969       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
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         // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
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     // Moves the value from the specified argument to *this. If the argument
0985     // has its function object allocated on the heap, move_assign will pass
0986     // its buffer to *this, and set the argument's buffer pointer to NULL.
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             // Don't operate on storage directly since union type doesn't relax
0997             // strict aliasing rules, despite of having member char type.
0998 #           if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
0999 #             pragma GCC diagnostic push
1000               // This warning is technically correct, but we don't want to pay the price for initializing
1001               // just to silence a warning: https://github.com/boostorg/function/issues/27
1002 #             pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1003 #             if (BOOST_GCC >= 120000)
1004                 // GCC 12 emits a different warning: https://github.com/boostorg/function/issues/42
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 // False positive in GCC 11/12 for empty function objects (function_n_test.cpp:673)
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 // Poison comparisons between boost::function objects of the same type.
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   // Move constructors
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 } // end namespace boost
1149 
1150 #if defined(BOOST_MSVC)
1151 #   pragma warning( pop )
1152 #endif
1153 
1154 // Resolve C++20 issue with fn == bind(...)
1155 // https://github.com/boostorg/function/issues/45
1156 
1157 namespace boost
1158 {
1159 
1160 namespace _bi
1161 {
1162 
1163 template<class R, class F, class L> class bind_t;
1164 
1165 } // namespace _bi
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 } // namespace boost
1178 
1179 #endif // #ifndef BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP_INCLUDED