function_template.hpp 32 KB

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