function_template.hpp 36 KB

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