Back to home page

EIC code displayed by LXR

 
 

    


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 // 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