function_template.hpp 42 KB

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