LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/function - function_template.hpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 109 121 90.1 %
Date: 2026-06-25 07:23:51 Functions: 184 493 37.3 %

          Line data    Source code
       1             : #ifndef BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP_INCLUDED
       2             : #define BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP_INCLUDED
       3             : 
       4             : // Boost.Function library
       5             : 
       6             : //  Copyright Douglas Gregor 2001-2006
       7             : //  Copyright Emil Dotchevski 2007
       8             : //  Use, modification and distribution is subject to the Boost Software License, Version 1.0.
       9             : //  (See accompanying file LICENSE_1_0.txt or copy at
      10             : //  http://www.boost.org/LICENSE_1_0.txt)
      11             : 
      12             : // For more information, see http://www.boost.org
      13             : 
      14             : #include <boost/function/function_base.hpp>
      15             : #include <boost/core/no_exceptions_support.hpp>
      16             : #include <boost/mem_fn.hpp>
      17             : #include <boost/throw_exception.hpp>
      18             : #include <boost/config.hpp>
      19             : #include <algorithm>
      20             : #include <cassert>
      21             : #include <type_traits>
      22             : 
      23             : #if defined(BOOST_MSVC)
      24             : #   pragma warning( push )
      25             : #   pragma warning( disable : 4127 ) // "conditional expression is constant"
      26             : #endif
      27             : 
      28             : namespace boost {
      29             :   namespace detail {
      30             :     namespace function {
      31             :       template<
      32             :         typename FunctionPtr,
      33             :         typename R,
      34             :         typename... T
      35             :         >
      36             :       struct function_invoker
      37             :       {
      38             :         static R invoke(function_buffer& function_ptr,
      39             :                         T... a)
      40             :         {
      41             :           FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
      42             :           return f(static_cast<T&&>(a)...);
      43             :         }
      44             :       };
      45             : 
      46             :       template<
      47             :         typename FunctionPtr,
      48             :         typename R,
      49             :         typename... T
      50             :         >
      51             :       struct void_function_invoker
      52             :       {
      53             :         static void
      54         731 :         invoke(function_buffer& function_ptr,
      55             :                T... a)
      56             : 
      57             :         {
      58         731 :           FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
      59         731 :           f(static_cast<T&&>(a)...);
      60         731 :         }
      61             :       };
      62             : 
      63             :       template<
      64             :         typename FunctionObj,
      65             :         typename R,
      66             :         typename... T
      67             :       >
      68             :       struct function_obj_invoker
      69             :       {
      70        1319 :         static R invoke(function_buffer& function_obj_ptr,
      71             :                         T... a)
      72             : 
      73             :         {
      74             :           FunctionObj* f;
      75             :           if (function_allows_small_object_optimization<FunctionObj>::value)
      76        1315 :             f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
      77             :           else
      78           4 :             f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
      79        1319 :           return (*f)(static_cast<T&&>(a)...);
      80             :         }
      81             :       };
      82             : 
      83             :       template<
      84             :         typename FunctionObj,
      85             :         typename R,
      86             :         typename... T
      87             :       >
      88             :       struct void_function_obj_invoker
      89             :       {
      90             :         static void
      91         815 :         invoke(function_buffer& function_obj_ptr,
      92             :                T... a)
      93             : 
      94             :         {
      95             :           FunctionObj* f;
      96             :           if (function_allows_small_object_optimization<FunctionObj>::value)
      97         372 :             f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
      98             :           else
      99         443 :             f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
     100         815 :           (*f)(static_cast<T&&>(a)...);
     101         815 :         }
     102             :       };
     103             : 
     104             :       template<
     105             :         typename FunctionObj,
     106             :         typename R,
     107             :         typename... T
     108             :       >
     109             :       struct function_ref_invoker
     110             :       {
     111             :         static R invoke(function_buffer& function_obj_ptr,
     112             :                         T... a)
     113             : 
     114             :         {
     115             :           FunctionObj* f =
     116             :             reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
     117             :           return (*f)(static_cast<T&&>(a)...);
     118             :         }
     119             :       };
     120             : 
     121             :       template<
     122             :         typename FunctionObj,
     123             :         typename R,
     124             :         typename... T
     125             :       >
     126             :       struct void_function_ref_invoker
     127             :       {
     128             :         static void
     129             :         invoke(function_buffer& function_obj_ptr,
     130             :                T... a)
     131             : 
     132             :         {
     133             :           FunctionObj* f =
     134             :             reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
     135             :           (*f)(static_cast<T&&>(a)...);
     136             :         }
     137             :       };
     138             : 
     139             :       /* Handle invocation of member pointers. */
     140             :       template<
     141             :         typename MemberPtr,
     142             :         typename R,
     143             :         typename... T
     144             :       >
     145             :       struct member_invoker
     146             :       {
     147             :         static R invoke(function_buffer& function_obj_ptr,
     148             :                         T... a)
     149             : 
     150             :         {
     151             :           MemberPtr* f =
     152             :             reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
     153             :           return boost::mem_fn(*f)(static_cast<T&&>(a)...);
     154             :         }
     155             :       };
     156             : 
     157             :       template<
     158             :         typename MemberPtr,
     159             :         typename R,
     160             :         typename... T
     161             :       >
     162             :       struct void_member_invoker
     163             :       {
     164             :         static void
     165             :         invoke(function_buffer& function_obj_ptr,
     166             :                T... a)
     167             : 
     168             :         {
     169             :           MemberPtr* f =
     170             :             reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
     171             :           boost::mem_fn(*f)(static_cast<T&&>(a)...);
     172             :         }
     173             :       };
     174             : 
     175             :       template<
     176             :         typename FunctionPtr,
     177             :         typename R,
     178             :         typename... T
     179             :       >
     180             :       struct get_function_invoker
     181             :       {
     182             :         typedef typename std::conditional<std::is_void<R>::value,
     183             :                             void_function_invoker<
     184             :                             FunctionPtr,
     185             :                             R,
     186             :                             T...
     187             :                           >,
     188             :                           function_invoker<
     189             :                             FunctionPtr,
     190             :                             R,
     191             :                             T...
     192             :                           >
     193             :                        >::type type;
     194             :       };
     195             : 
     196             :       template<
     197             :         typename FunctionObj,
     198             :         typename R,
     199             :         typename... T
     200             :        >
     201             :       struct get_function_obj_invoker
     202             :       {
     203             :         typedef typename std::conditional<std::is_void<R>::value,
     204             :                             void_function_obj_invoker<
     205             :                             FunctionObj,
     206             :                             R,
     207             :                             T...
     208             :                           >,
     209             :                           function_obj_invoker<
     210             :                             FunctionObj,
     211             :                             R,
     212             :                             T...
     213             :                           >
     214             :                        >::type type;
     215             :       };
     216             : 
     217             :       template<
     218             :         typename FunctionObj,
     219             :         typename R,
     220             :         typename... T
     221             :        >
     222             :       struct get_function_ref_invoker
     223             :       {
     224             :         typedef typename std::conditional<std::is_void<R>::value,
     225             :                             void_function_ref_invoker<
     226             :                             FunctionObj,
     227             :                             R,
     228             :                             T...
     229             :                           >,
     230             :                           function_ref_invoker<
     231             :                             FunctionObj,
     232             :                             R,
     233             :                             T...
     234             :                           >
     235             :                        >::type type;
     236             :       };
     237             : 
     238             :       /* Retrieve the appropriate invoker for a member pointer.  */
     239             :       template<
     240             :         typename MemberPtr,
     241             :         typename R,
     242             :         typename... T
     243             :        >
     244             :       struct get_member_invoker
     245             :       {
     246             :         typedef typename std::conditional<std::is_void<R>::value,
     247             :                             void_member_invoker<
     248             :                             MemberPtr,
     249             :                             R,
     250             :                             T...
     251             :                           >,
     252             :                           member_invoker<
     253             :                             MemberPtr,
     254             :                             R,
     255             :                             T...
     256             :                           >
     257             :                        >::type type;
     258             :       };
     259             : 
     260             :       /* Given the tag returned by get_function_tag, retrieve the
     261             :          actual invoker that will be used for the given function
     262             :          object.
     263             : 
     264             :          Each specialization contains an "apply_" nested class template
     265             :          that accepts the function object, return type, function
     266             :          argument types, and allocator. The resulting "apply_" class
     267             :          contains two typedefs, "invoker_type" and "manager_type",
     268             :          which correspond to the invoker and manager types. */
     269             :       template<typename Tag>
     270             :       struct get_invoker { };
     271             : 
     272             :       /* Retrieve the invoker for a function pointer. */
     273             :       template<>
     274             :       struct get_invoker<function_ptr_tag>
     275             :       {
     276             :         template<typename FunctionPtr,
     277             :                  typename R, typename... T>
     278             :         struct apply_
     279             :         {
     280             :           typedef typename get_function_invoker<
     281             :                              FunctionPtr,
     282             :                              R,
     283             :                              T...
     284             :                            >::type
     285             :             invoker_type;
     286             : 
     287             :           typedef functor_manager<FunctionPtr> manager_type;
     288             :         };
     289             : 
     290             :         template<typename FunctionPtr, typename Allocator,
     291             :                  typename R, typename... T>
     292             :         struct apply_a
     293             :         {
     294             :           typedef typename get_function_invoker<
     295             :                              FunctionPtr,
     296             :                              R,
     297             :                              T...
     298             :                            >::type
     299             :             invoker_type;
     300             : 
     301             :           typedef functor_manager<FunctionPtr> manager_type;
     302             :         };
     303             :       };
     304             : 
     305             :       /* Retrieve the invoker for a member pointer. */
     306             :       template<>
     307             :       struct get_invoker<member_ptr_tag>
     308             :       {
     309             :         template<typename MemberPtr,
     310             :                  typename R, typename... T>
     311             :         struct apply_
     312             :         {
     313             :           typedef typename get_member_invoker<
     314             :                              MemberPtr,
     315             :                              R,
     316             :                              T...
     317             :                            >::type
     318             :             invoker_type;
     319             : 
     320             :           typedef functor_manager<MemberPtr> manager_type;
     321             :         };
     322             : 
     323             :         template<typename MemberPtr, typename Allocator,
     324             :                  typename R, typename... T>
     325             :         struct apply_a
     326             :         {
     327             :           typedef typename get_member_invoker<
     328             :                              MemberPtr,
     329             :                              R,
     330             :                              T...
     331             :                            >::type
     332             :             invoker_type;
     333             : 
     334             :           typedef functor_manager<MemberPtr> manager_type;
     335             :         };
     336             :       };
     337             : 
     338             :       /* Retrieve the invoker for a function object. */
     339             :       template<>
     340             :       struct get_invoker<function_obj_tag>
     341             :       {
     342             :         template<typename FunctionObj,
     343             :                  typename R, typename... T>
     344             :         struct apply_
     345             :         {
     346             :           typedef typename get_function_obj_invoker<
     347             :                              FunctionObj,
     348             :                              R,
     349             :                              T...
     350             :                            >::type
     351             :             invoker_type;
     352             : 
     353             :           typedef functor_manager<FunctionObj> manager_type;
     354             :         };
     355             : 
     356             :         template<typename FunctionObj, typename Allocator,
     357             :                  typename R, typename... T>
     358             :         struct apply_a
     359             :         {
     360             :           typedef typename get_function_obj_invoker<
     361             :                              FunctionObj,
     362             :                              R,
     363             :                              T...
     364             :                            >::type
     365             :             invoker_type;
     366             : 
     367             :           typedef functor_manager_a<FunctionObj, Allocator> manager_type;
     368             :         };
     369             :       };
     370             : 
     371             :       /* Retrieve the invoker for a reference to a function object. */
     372             :       template<>
     373             :       struct get_invoker<function_obj_ref_tag>
     374             :       {
     375             :         template<typename RefWrapper,
     376             :                  typename R, typename... T>
     377             :         struct apply_
     378             :         {
     379             :           typedef typename get_function_ref_invoker<
     380             :                              typename RefWrapper::type,
     381             :                              R,
     382             :                              T...
     383             :                            >::type
     384             :             invoker_type;
     385             : 
     386             :           typedef reference_manager<typename RefWrapper::type> manager_type;
     387             :         };
     388             : 
     389             :         template<typename RefWrapper, typename Allocator,
     390             :                  typename R, typename... T>
     391             :         struct apply_a
     392             :         {
     393             :           typedef typename get_function_ref_invoker<
     394             :                              typename RefWrapper::type,
     395             :                              R,
     396             :                              T...
     397             :                            >::type
     398             :             invoker_type;
     399             : 
     400             :           typedef reference_manager<typename RefWrapper::type> manager_type;
     401             :         };
     402             :       };
     403             : 
     404             : 
     405             :       /**
     406             :        * vtable for a specific boost::function instance. This
     407             :        * structure must be an aggregate so that we can use static
     408             :        * initialization in boost::function's assign_to and assign_to_a
     409             :        * members. It therefore cannot have any constructors,
     410             :        * destructors, base classes, etc.
     411             :        */
     412             :       template<typename R, typename... T>
     413             :       struct basic_vtable
     414             :       {
     415             :         typedef R         result_type;
     416             : 
     417             :         typedef result_type (*invoker_type)(function_buffer&
     418             :                                            ,
     419             :                                             T...);
     420             : 
     421             :         template<typename F>
     422      104519 :         bool assign_to(F f, function_buffer& functor) const
     423             :         {
     424             :           typedef typename get_function_tag<F>::type tag;
     425      104519 :           return assign_to(std::move(f), functor, tag());
     426           0 :         }
     427             :         template<typename F,typename Allocator>
     428             :         bool assign_to_a(F f, function_buffer& functor, Allocator a) const
     429             :         {
     430             :           typedef typename get_function_tag<F>::type tag;
     431             :           return assign_to_a(std::move(f), functor, a, tag());
     432             :         }
     433             : 
     434      103422 :         void clear(function_buffer& functor) const
     435             :         {
     436             : #if defined(BOOST_GCC) && (__GNUC__ >= 11)
     437             : # pragma GCC diagnostic push
     438             : // False positive in GCC 11/12 for empty function objects
     439             : # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
     440             : #endif
     441      103422 :           if (base.manager)
     442      103422 :             base.manager(functor, functor, destroy_functor_tag);
     443             : #if defined(BOOST_GCC) && (__GNUC__ >= 11)
     444             : # pragma GCC diagnostic pop
     445             : #endif
     446      103422 :         }
     447             : 
     448             :       private:
     449             :         // Function pointers
     450             :         template<typename FunctionPtr>
     451             :         bool
     452      101762 :         assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
     453             :         {
     454      101762 :           this->clear(functor);
     455      101762 :           if (f) {
     456      101762 :             functor.members.func_ptr = reinterpret_cast<void (*)()>(f);
     457      101762 :             return true;
     458             :           } else {
     459           0 :             return false;
     460             :           }
     461      101762 :         }
     462             :         template<typename FunctionPtr,typename Allocator>
     463             :         bool
     464             :         assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
     465             :         {
     466             :           return assign_to(std::move(f),functor,function_ptr_tag());
     467             :         }
     468             : 
     469             :         // Member pointers
     470             :         template<typename MemberPtr>
     471             :         bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
     472             :         {
     473             :           // DPG TBD: Add explicit support for member function
     474             :           // objects, so we invoke through mem_fn() but we retain the
     475             :           // right target_type() values.
     476             :           if (f) {
     477             :             this->assign_to(boost::mem_fn(f), functor);
     478             :             return true;
     479             :           } else {
     480             :             return false;
     481             :           }
     482             :         }
     483             :         template<typename MemberPtr,typename Allocator>
     484             :         bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const
     485             :         {
     486             :           // DPG TBD: Add explicit support for member function
     487             :           // objects, so we invoke through mem_fn() but we retain the
     488             :           // right target_type() values.
     489             :           if (f) {
     490             :             this->assign_to_a(boost::mem_fn(f), functor, a);
     491             :             return true;
     492             :           } else {
     493             :             return false;
     494             :           }
     495             :         }
     496             : 
     497             :         // Function objects
     498             :         // Assign to a function object using the small object optimization
     499             :         template<typename FunctionObj>
     500             :         void
     501        1635 :         assign_functor(FunctionObj f, function_buffer& functor, std::true_type) const
     502             :         {
     503        1635 :           new (reinterpret_cast<void*>(functor.data)) FunctionObj(std::move(f));
     504        1635 :         }
     505             :         template<typename FunctionObj,typename Allocator>
     506             :         void
     507             :         assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, std::true_type) const
     508             :         {
     509             :           assign_functor(std::move(f),functor,std::true_type());
     510             :         }
     511             : 
     512             :         // Assign to a function object allocated on the heap.
     513             :         template<typename FunctionObj>
     514             :         void
     515        1122 :         assign_functor(FunctionObj f, function_buffer& functor, std::false_type) const
     516             :         {
     517        1122 :           functor.members.obj_ptr = new FunctionObj(std::move(f));
     518        1122 :         }
     519             :         template<typename FunctionObj,typename Allocator>
     520             :         void
     521             :         assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, std::false_type) const
     522             :         {
     523             :           typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
     524             : 
     525             :           using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
     526             :           using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
     527             : 
     528             :           wrapper_allocator_type wrapper_allocator(a);
     529             :           wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
     530             :           std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, functor_wrapper_type(f,a));
     531             : 
     532             :           functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
     533             :           functor.members.obj_ptr = new_f;
     534             :         }
     535             : 
     536             :         template<typename FunctionObj>
     537             :         bool
     538        2757 :         assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
     539             :         {
     540        2757 :           if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
     541        2757 :             assign_functor(std::move(f), functor,
     542             :                            std::integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>());
     543        2757 :             return true;
     544             :           } else {
     545           0 :             return false;
     546             :           }
     547        2757 :         }
     548             :         template<typename FunctionObj,typename Allocator>
     549             :         bool
     550             :         assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
     551             :         {
     552             :           if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
     553             :             assign_functor_a(std::move(f), functor, a,
     554             :                            std::integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>());
     555             :             return true;
     556             :           } else {
     557             :             return false;
     558             :           }
     559             :         }
     560             : 
     561             :         // Reference to a function object
     562             :         template<typename FunctionObj>
     563             :         bool
     564             :         assign_to(const reference_wrapper<FunctionObj>& f,
     565             :                   function_buffer& functor, function_obj_ref_tag) const
     566             :         {
     567             :           functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer());
     568             :           functor.members.obj_ref.is_const_qualified = std::is_const<FunctionObj>::value;
     569             :           functor.members.obj_ref.is_volatile_qualified = std::is_volatile<FunctionObj>::value;
     570             :           return true;
     571             :         }
     572             :         template<typename FunctionObj,typename Allocator>
     573             :         bool
     574             :         assign_to_a(const reference_wrapper<FunctionObj>& f,
     575             :                   function_buffer& functor, Allocator, function_obj_ref_tag) const
     576             :         {
     577             :           return assign_to(f,functor,function_obj_ref_tag());
     578             :         }
     579             : 
     580             :       public:
     581             :         vtable_base base;
     582             :         invoker_type invoker;
     583             :       };
     584             : 
     585             :       template <typename... T>
     586             :       struct variadic_function_base
     587             :       {};
     588             : 
     589             :       template <typename T1>
     590             :       struct variadic_function_base<T1>
     591             :       {
     592             :         typedef T1 argument_type;
     593             :         typedef T1 arg1_type;
     594             :       };
     595             : 
     596             :       template <typename T1, typename T2>
     597             :       struct variadic_function_base<T1, T2>
     598             :       {
     599             :         typedef T1 first_argument_type;
     600             :         typedef T2 second_argument_type;
     601             :         typedef T1 arg1_type;
     602             :         typedef T2 arg2_type;
     603             :       };
     604             : 
     605             :       template <typename T1, typename T2, typename T3>
     606             :       struct variadic_function_base<T1, T2, T3>
     607             :       {
     608             :         typedef T1 arg1_type;
     609             :         typedef T2 arg2_type;
     610             :         typedef T3 arg3_type;
     611             :       };
     612             : 
     613             :       template <typename T1, typename T2, typename T3, typename T4>
     614             :       struct variadic_function_base<T1, T2, T3, T4>
     615             :       {
     616             :         typedef T1 arg1_type;
     617             :         typedef T2 arg2_type;
     618             :         typedef T3 arg3_type;
     619             :         typedef T4 arg4_type;
     620             :       };
     621             : 
     622             :       template <typename T1, typename T2, typename T3, typename T4, typename T5>
     623             :       struct variadic_function_base<T1, T2, T3, T4, T5>
     624             :       {
     625             :         typedef T1 arg1_type;
     626             :         typedef T2 arg2_type;
     627             :         typedef T3 arg3_type;
     628             :         typedef T4 arg4_type;
     629             :         typedef T5 arg5_type;
     630             :       };
     631             : 
     632             :       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
     633             :       struct variadic_function_base<T1, T2, T3, T4, T5, T6>
     634             :       {
     635             :         typedef T1 arg1_type;
     636             :         typedef T2 arg2_type;
     637             :         typedef T3 arg3_type;
     638             :         typedef T4 arg4_type;
     639             :         typedef T5 arg5_type;
     640             :         typedef T6 arg6_type;
     641             :       };
     642             : 
     643             :       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
     644             :       struct variadic_function_base<T1, T2, T3, T4, T5, T6, T7>
     645             :       {
     646             :         typedef T1 arg1_type;
     647             :         typedef T2 arg2_type;
     648             :         typedef T3 arg3_type;
     649             :         typedef T4 arg4_type;
     650             :         typedef T5 arg5_type;
     651             :         typedef T6 arg6_type;
     652             :         typedef T7 arg7_type;
     653             :       };
     654             : 
     655             :       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
     656             :       struct variadic_function_base<T1, T2, T3, T4, T5, T6, T7, T8>
     657             :       {
     658             :         typedef T1 arg1_type;
     659             :         typedef T2 arg2_type;
     660             :         typedef T3 arg3_type;
     661             :         typedef T4 arg4_type;
     662             :         typedef T5 arg5_type;
     663             :         typedef T6 arg6_type;
     664             :         typedef T7 arg7_type;
     665             :         typedef T8 arg8_type;
     666             :       };
     667             : 
     668             :       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
     669             :       struct variadic_function_base<T1, T2, T3, T4, T5, T6, T7, T8, T9>
     670             :       {
     671             :         typedef T1 arg1_type;
     672             :         typedef T2 arg2_type;
     673             :         typedef T3 arg3_type;
     674             :         typedef T4 arg4_type;
     675             :         typedef T5 arg5_type;
     676             :         typedef T6 arg6_type;
     677             :         typedef T7 arg7_type;
     678             :         typedef T8 arg8_type;
     679             :         typedef T9 arg9_type;
     680             :       };
     681             : 
     682             :       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
     683             :       struct variadic_function_base<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
     684             :       {
     685             :         typedef T1 arg1_type;
     686             :         typedef T2 arg2_type;
     687             :         typedef T3 arg3_type;
     688             :         typedef T4 arg4_type;
     689             :         typedef T5 arg5_type;
     690             :         typedef T6 arg6_type;
     691             :         typedef T7 arg7_type;
     692             :         typedef T8 arg8_type;
     693             :         typedef T9 arg9_type;
     694             :         typedef T10 arg10_type;
     695             :       };
     696             : 
     697             : #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000
     698             : 
     699             :       template<class T> struct is_trivially_copyable: std::integral_constant<bool,
     700             :         __has_trivial_copy(T) && __has_trivial_assign(T) && __has_trivial_destructor(T)> {};
     701             : 
     702             : #else
     703             : 
     704             :       using std::is_trivially_copyable;
     705             : 
     706             : #endif
     707             : 
     708             :     } // end namespace function
     709             :   } // end namespace detail
     710             : 
     711             :   template<
     712             :     typename R,
     713             :     typename... T
     714             :   >
     715             :   class function_n : public function_base
     716             :                                 , public detail::function::variadic_function_base<T...>
     717             :   {
     718             :   public:
     719             :     typedef R         result_type;
     720             : 
     721             :   private:
     722             :     typedef boost::detail::function::basic_vtable<
     723             :               R, T...>
     724             :       vtable_type;
     725             : 
     726        6661 :     vtable_type* get_vtable() const {
     727        6661 :       return reinterpret_cast<vtable_type*>(
     728        6661 :                reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
     729             :     }
     730             : 
     731             :     struct clear_type {};
     732             : 
     733             :   public:
     734             :     // add signature for boost::lambda
     735             :     template<typename Args>
     736             :     struct sig
     737             :     {
     738             :       typedef result_type type;
     739             :     };
     740             : 
     741             :     BOOST_STATIC_CONSTANT(int, arity = sizeof...(T));
     742             : 
     743             :     typedef function_n self_type;
     744             : 
     745        6661 :     BOOST_DEFAULTED_FUNCTION(function_n(), : function_base() {})
     746             : 
     747             :     // MSVC chokes if the following two constructors are collapsed into
     748             :     // one with a default parameter.
     749             :     template<typename Functor>
     750      104519 :     function_n(Functor f
     751             :                             ,typename std::enable_if<
     752             :                              !std::is_integral<Functor>::value,
     753             :                                         int>::type = 0
     754             :                             ) :
     755      104519 :       function_base()
     756             :     {
     757      104519 :       this->assign_to(std::move(f));
     758      104519 :     }
     759             :     template<typename Functor,typename Allocator>
     760             :     function_n(Functor f, Allocator a
     761             :                             ,typename std::enable_if<
     762             :                               !std::is_integral<Functor>::value,
     763             :                                         int>::type = 0
     764             :                             ) :
     765             :       function_base()
     766             :     {
     767             :       this->assign_to_a(std::move(f),a);
     768             :     }
     769             : 
     770             :     function_n(clear_type*) : function_base() { }
     771             : 
     772      106562 :     function_n(const function_n& f) : function_base()
     773             :     {
     774      106562 :       this->assign_to_own(f);
     775      106562 :     }
     776             : 
     777        4088 :     function_n(function_n&& f) : function_base()
     778             :     {
     779        4088 :       this->move_assign(f);
     780        4088 :     }
     781             : 
     782      115631 :     ~function_n() { clear(); }
     783             : 
     784        2865 :     result_type operator()(T... a) const
     785             :     {
     786        2865 :       if (this->empty())
     787           0 :         boost::throw_exception(bad_function_call());
     788             : 
     789        5730 :       return get_vtable()->invoker
     790        2865 :                (this->functor, static_cast<T&&>(a)...);
     791           0 :     }
     792             : 
     793             :     // The distinction between when to use function_n and
     794             :     // when to use self_type is obnoxious. MSVC cannot handle self_type as
     795             :     // the return type of these assignment operators, but Borland C++ cannot
     796             :     // handle function_n as the type of the temporary to
     797             :     // construct.
     798             :     template<typename Functor>
     799             :     typename std::enable_if<
     800             :                   !std::is_integral<Functor>::value,
     801             :                function_n&>::type
     802             :     operator=(Functor f)
     803             :     {
     804             :       this->clear();
     805             :       BOOST_TRY  {
     806             :         this->assign_to(f);
     807             :       } BOOST_CATCH (...) {
     808             :         vtable = 0;
     809             :         BOOST_RETHROW;
     810             :       }
     811             :       BOOST_CATCH_END
     812             :       return *this;
     813             :     }
     814             :     template<typename Functor,typename Allocator>
     815             :     void assign(Functor f, Allocator a)
     816             :     {
     817             :       this->clear();
     818             :       BOOST_TRY{
     819             :         this->assign_to_a(f,a);
     820             :       } BOOST_CATCH (...) {
     821             :         vtable = 0;
     822             :         BOOST_RETHROW;
     823             :       }
     824             :       BOOST_CATCH_END
     825             :     }
     826             : 
     827             :     function_n& operator=(clear_type*)
     828             :     {
     829             :       this->clear();
     830             :       return *this;
     831             :     }
     832             : 
     833             :     // Assignment from another function_n
     834             :     function_n& operator=(const function_n& f)
     835             :     {
     836             :       if (&f == this)
     837             :         return *this;
     838             : 
     839             :       this->clear();
     840             :       BOOST_TRY {
     841             :         this->assign_to_own(f);
     842             :       } BOOST_CATCH (...) {
     843             :         vtable = 0;
     844             :         BOOST_RETHROW;
     845             :       }
     846             :       BOOST_CATCH_END
     847             :       return *this;
     848             :     }
     849             : 
     850             :     // Move assignment from another function_n
     851             :     function_n& operator=(function_n&& f)
     852             :     {
     853             :       if (&f == this)
     854             :         return *this;
     855             : 
     856             :       this->clear();
     857             :       BOOST_TRY {
     858             :         this->move_assign(f);
     859             :       } BOOST_CATCH (...) {
     860             :         vtable = 0;
     861             :         BOOST_RETHROW;
     862             :       }
     863             :       BOOST_CATCH_END
     864             :       return *this;
     865             :     }
     866             : 
     867         858 :     void swap(function_n& other)
     868             :     {
     869         858 :       if (&other == this)
     870           0 :         return;
     871             : 
     872         858 :       function_n tmp;
     873         858 :       tmp.move_assign(*this);
     874         858 :       this->move_assign(other);
     875         858 :       other.move_assign(tmp);
     876         858 :     }
     877             : 
     878             :     // Clear out a target, if there is one
     879      119573 :     void clear()
     880             :     {
     881      119573 :       if (vtable) {
     882      104882 :         if (!this->has_trivial_copy_and_destroy())
     883        1660 :           get_vtable()->clear(this->functor);
     884      104882 :         vtable = 0;
     885      104882 :       }
     886      119573 :     }
     887             : 
     888        3503 :     explicit operator bool () const { return !this->empty(); }
     889             : 
     890             :   private:
     891      106562 :     void assign_to_own(const function_n& f)
     892             :     {
     893      106562 :       if (!f.empty()) {
     894      102620 :         this->vtable = f.vtable;
     895      102620 :         if (this->has_trivial_copy_and_destroy()) {
     896             :           // Don't operate on storage directly since union type doesn't relax
     897             :           // strict aliasing rules, despite of having member char type.
     898             : #         if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
     899             : #           pragma GCC diagnostic push
     900             :             // This warning is technically correct, but we don't want to pay the price for initializing
     901             :             // just to silence a warning: https://github.com/boostorg/function/issues/27
     902             : #           pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
     903             : #           if (BOOST_GCC >= 110000)
     904             :               // GCC 11.3, 12 emit a different warning: https://github.com/boostorg/function/issues/42
     905             : #             pragma GCC diagnostic ignored "-Wuninitialized"
     906             : #           endif
     907             : #         endif
     908      101908 :           std::memcpy(this->functor.data, f.functor.data, sizeof(boost::detail::function::function_buffer));
     909             : #         if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
     910             : #           pragma GCC diagnostic pop
     911             : #         endif
     912      101908 :         } else
     913         712 :           get_vtable()->base.manager(f.functor, this->functor,
     914             :                                      boost::detail::function::clone_functor_tag);
     915      102620 :       }
     916      106562 :     }
     917             : 
     918             :     template<typename Functor>
     919      104519 :     void assign_to(Functor f)
     920             :     {
     921             :       using boost::detail::function::vtable_base;
     922             : 
     923             :       typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
     924             :       typedef boost::detail::function::get_invoker<tag> get_invoker;
     925             :       typedef typename get_invoker::
     926             :                          template apply_<Functor, R,
     927             :                         T...>
     928             :         handler_type;
     929             : 
     930             :       typedef typename handler_type::invoker_type invoker_type;
     931             :       typedef typename handler_type::manager_type manager_type;
     932             : 
     933             :       // Note: it is extremely important that this initialization use
     934             :       // static initialization. Otherwise, we will have a race
     935             :       // condition here in multi-threaded code. See
     936             :       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
     937             :       static const vtable_type stored_vtable =
     938             :         { { &manager_type::manage }, &invoker_type::invoke };
     939             : 
     940      104519 :       if (stored_vtable.assign_to(std::move(f), functor)) {
     941      104519 :         std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
     942             :         // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
     943             :         if (boost::detail::function::is_trivially_copyable<Functor>::value &&
     944             :             boost::detail::function::function_allows_small_object_optimization<Functor>::value)
     945      103223 :           value |= static_cast<std::size_t>(0x01);
     946      104519 :         vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
     947      104519 :       } else
     948           0 :         vtable = 0;
     949      104519 :     }
     950             : 
     951             :     template<typename Functor,typename Allocator>
     952             :     void assign_to_a(Functor f,Allocator a)
     953             :     {
     954             :       using boost::detail::function::vtable_base;
     955             : 
     956             :       typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
     957             :       typedef boost::detail::function::get_invoker<tag> get_invoker;
     958             :       typedef typename get_invoker::
     959             :                          template apply_a<Functor, Allocator, R,
     960             :                          T...>
     961             :         handler_type;
     962             : 
     963             :       typedef typename handler_type::invoker_type invoker_type;
     964             :       typedef typename handler_type::manager_type manager_type;
     965             : 
     966             :       // Note: it is extremely important that this initialization use
     967             :       // static initialization. Otherwise, we will have a race
     968             :       // condition here in multi-threaded code. See
     969             :       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
     970             :       static const vtable_type stored_vtable =
     971             :         { { &manager_type::manage }, &invoker_type::invoke };
     972             : 
     973             :       if (stored_vtable.assign_to_a(std::move(f), functor, a)) {
     974             :         std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
     975             :         // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
     976             :         if (boost::detail::function::is_trivially_copyable<Functor>::value &&
     977             :             boost::detail::function::function_allows_small_object_optimization<Functor>::value)
     978             :           value |= static_cast<std::size_t>(0x01);
     979             :         vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
     980             :       } else
     981             :         vtable = 0;
     982             :     }
     983             : 
     984             :     // Moves the value from the specified argument to *this. If the argument
     985             :     // has its function object allocated on the heap, move_assign will pass
     986             :     // its buffer to *this, and set the argument's buffer pointer to NULL.
     987        6662 :     void move_assign(function_n& f)
     988             :     {
     989        6662 :       if (&f == this)
     990           0 :         return;
     991             : 
     992             :       BOOST_TRY {
     993        6662 :         if (!f.empty()) {
     994        1862 :           this->vtable = f.vtable;
     995        1862 :           if (this->has_trivial_copy_and_destroy()) {
     996             :             // Don't operate on storage directly since union type doesn't relax
     997             :             // strict aliasing rules, despite of having member char type.
     998             : #           if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
     999             : #             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         438 :             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         438 :           } 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        1424 :             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        1862 :           f.vtable = 0;
    1024        1862 :         } else {
    1025        4800 :           clear();
    1026             :         }
    1027        6662 :       } BOOST_CATCH (...) {
    1028           0 :         vtable = 0;
    1029           0 :         BOOST_RETHROW;
    1030           0 :       }
    1031             :       BOOST_CATCH_END
    1032        6662 :     }
    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        9890 :   BOOST_DEFAULTED_FUNCTION(function(), : base_type() {})
    1077             : 
    1078             :   template<typename Functor>
    1079      209038 :   function(Functor f
    1080             :            ,typename std::enable_if<
    1081             :                           !std::is_integral<Functor>::value,
    1082             :                        int>::type = 0
    1083             :            ) :
    1084      104519 :     base_type(std::move(f))
    1085      104519 :   {
    1086      209038 :   }
    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      213124 :   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        8176 :   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         858 :   operator=(Functor f)
    1124             :   {
    1125         858 :     self_type(f).swap(*this);
    1126         858 :     return *this;
    1127           0 :   }
    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

Generated by: LCOV version 1.16