function_template.hpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  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 (base.manager)
  449. base.manager(functor, functor, destroy_functor_tag);
  450. }
  451. private:
  452. // Function pointers
  453. template<typename FunctionPtr>
  454. bool
  455. assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
  456. {
  457. this->clear(functor);
  458. if (f) {
  459. // should be a reinterpret cast, but some compilers insist
  460. // on giving cv-qualifiers to free functions
  461. functor.members.func_ptr = reinterpret_cast<void (*)()>(f);
  462. return true;
  463. } else {
  464. return false;
  465. }
  466. }
  467. template<typename FunctionPtr,typename Allocator>
  468. bool
  469. assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
  470. {
  471. return assign_to(f,functor,function_ptr_tag());
  472. }
  473. // Member pointers
  474. #if BOOST_FUNCTION_NUM_ARGS > 0
  475. template<typename MemberPtr>
  476. bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
  477. {
  478. // DPG TBD: Add explicit support for member function
  479. // objects, so we invoke through mem_fn() but we retain the
  480. // right target_type() values.
  481. if (f) {
  482. this->assign_to(boost::mem_fn(f), functor);
  483. return true;
  484. } else {
  485. return false;
  486. }
  487. }
  488. template<typename MemberPtr,typename Allocator>
  489. bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const
  490. {
  491. // DPG TBD: Add explicit support for member function
  492. // objects, so we invoke through mem_fn() but we retain the
  493. // right target_type() values.
  494. if (f) {
  495. this->assign_to_a(boost::mem_fn(f), functor, a);
  496. return true;
  497. } else {
  498. return false;
  499. }
  500. }
  501. #endif // BOOST_FUNCTION_NUM_ARGS > 0
  502. // Function objects
  503. // Assign to a function object using the small object optimization
  504. template<typename FunctionObj>
  505. void
  506. assign_functor(FunctionObj f, function_buffer& functor, true_type) const
  507. {
  508. new (reinterpret_cast<void*>(functor.data)) FunctionObj(f);
  509. }
  510. template<typename FunctionObj,typename Allocator>
  511. void
  512. assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, true_type) const
  513. {
  514. assign_functor(f,functor,true_type());
  515. }
  516. // Assign to a function object allocated on the heap.
  517. template<typename FunctionObj>
  518. void
  519. assign_functor(FunctionObj f, function_buffer& functor, false_type) const
  520. {
  521. functor.members.obj_ptr = new FunctionObj(f);
  522. }
  523. template<typename FunctionObj,typename Allocator>
  524. void
  525. assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, false_type) const
  526. {
  527. typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
  528. #if defined(BOOST_NO_CXX11_ALLOCATOR)
  529. typedef typename Allocator::template rebind<functor_wrapper_type>::other
  530. wrapper_allocator_type;
  531. typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
  532. #else
  533. using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
  534. using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
  535. #endif
  536. wrapper_allocator_type wrapper_allocator(a);
  537. wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
  538. #if defined(BOOST_NO_CXX11_ALLOCATOR)
  539. wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
  540. #else
  541. std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, functor_wrapper_type(f,a));
  542. #endif
  543. functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
  544. functor.members.obj_ptr = new_f;
  545. }
  546. template<typename FunctionObj>
  547. bool
  548. assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
  549. {
  550. if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
  551. assign_functor(f, functor,
  552. integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>());
  553. return true;
  554. } else {
  555. return false;
  556. }
  557. }
  558. template<typename FunctionObj,typename Allocator>
  559. bool
  560. assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
  561. {
  562. if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
  563. assign_functor_a(f, functor, a,
  564. integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>());
  565. return true;
  566. } else {
  567. return false;
  568. }
  569. }
  570. // Reference to a function object
  571. template<typename FunctionObj>
  572. bool
  573. assign_to(const reference_wrapper<FunctionObj>& f,
  574. function_buffer& functor, function_obj_ref_tag) const
  575. {
  576. functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer());
  577. functor.members.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
  578. functor.members.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
  579. return true;
  580. }
  581. template<typename FunctionObj,typename Allocator>
  582. bool
  583. assign_to_a(const reference_wrapper<FunctionObj>& f,
  584. function_buffer& functor, Allocator, function_obj_ref_tag) const
  585. {
  586. return assign_to(f,functor,function_obj_ref_tag());
  587. }
  588. public:
  589. vtable_base base;
  590. invoker_type invoker;
  591. };
  592. } // end namespace function
  593. } // end namespace detail
  594. template<
  595. typename R BOOST_FUNCTION_COMMA
  596. BOOST_FUNCTION_TEMPLATE_PARMS
  597. >
  598. class BOOST_FUNCTION_FUNCTION : public function_base
  599. {
  600. public:
  601. #ifndef BOOST_NO_VOID_RETURNS
  602. typedef R result_type;
  603. #else
  604. typedef typename boost::detail::function::function_return_type<R>::type
  605. result_type;
  606. #endif // BOOST_NO_VOID_RETURNS
  607. private:
  608. typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
  609. R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
  610. vtable_type;
  611. vtable_type* get_vtable() const {
  612. return reinterpret_cast<vtable_type*>(
  613. reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
  614. }
  615. struct clear_type {};
  616. public:
  617. BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
  618. // add signature for boost::lambda
  619. template<typename Args>
  620. struct sig
  621. {
  622. typedef result_type type;
  623. };
  624. #if BOOST_FUNCTION_NUM_ARGS == 1
  625. typedef T0 argument_type;
  626. #elif BOOST_FUNCTION_NUM_ARGS == 2
  627. typedef T0 first_argument_type;
  628. typedef T1 second_argument_type;
  629. #endif
  630. BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
  631. BOOST_FUNCTION_ARG_TYPES
  632. typedef BOOST_FUNCTION_FUNCTION self_type;
  633. BOOST_DEFAULTED_FUNCTION(BOOST_FUNCTION_FUNCTION(), : function_base() {})
  634. // MSVC chokes if the following two constructors are collapsed into
  635. // one with a default parameter.
  636. template<typename Functor>
  637. BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
  638. #ifndef BOOST_NO_SFINAE
  639. ,typename boost::enable_if_<
  640. !(is_integral<Functor>::value),
  641. int>::type = 0
  642. #endif // BOOST_NO_SFINAE
  643. ) :
  644. function_base()
  645. {
  646. this->assign_to(f);
  647. }
  648. template<typename Functor,typename Allocator>
  649. BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
  650. #ifndef BOOST_NO_SFINAE
  651. ,typename boost::enable_if_<
  652. !(is_integral<Functor>::value),
  653. int>::type = 0
  654. #endif // BOOST_NO_SFINAE
  655. ) :
  656. function_base()
  657. {
  658. this->assign_to_a(f,a);
  659. }
  660. #ifndef BOOST_NO_SFINAE
  661. BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
  662. #else
  663. BOOST_FUNCTION_FUNCTION(int zero) : function_base()
  664. {
  665. BOOST_ASSERT(zero == 0);
  666. }
  667. #endif
  668. BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
  669. {
  670. this->assign_to_own(f);
  671. }
  672. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  673. BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
  674. {
  675. this->move_assign(f);
  676. }
  677. #endif
  678. ~BOOST_FUNCTION_FUNCTION() { clear(); }
  679. result_type operator()(BOOST_FUNCTION_PARMS) const
  680. {
  681. if (this->empty())
  682. boost::throw_exception(bad_function_call());
  683. return get_vtable()->invoker
  684. (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
  685. }
  686. // The distinction between when to use BOOST_FUNCTION_FUNCTION and
  687. // when to use self_type is obnoxious. MSVC cannot handle self_type as
  688. // the return type of these assignment operators, but Borland C++ cannot
  689. // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
  690. // construct.
  691. template<typename Functor>
  692. #ifndef BOOST_NO_SFINAE
  693. typename boost::enable_if_<
  694. !(is_integral<Functor>::value),
  695. BOOST_FUNCTION_FUNCTION&>::type
  696. #else
  697. BOOST_FUNCTION_FUNCTION&
  698. #endif
  699. operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
  700. {
  701. this->clear();
  702. BOOST_TRY {
  703. this->assign_to(f);
  704. } BOOST_CATCH (...) {
  705. vtable = 0;
  706. BOOST_RETHROW;
  707. }
  708. BOOST_CATCH_END
  709. return *this;
  710. }
  711. template<typename Functor,typename Allocator>
  712. void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
  713. {
  714. this->clear();
  715. BOOST_TRY{
  716. this->assign_to_a(f,a);
  717. } BOOST_CATCH (...) {
  718. vtable = 0;
  719. BOOST_RETHROW;
  720. }
  721. BOOST_CATCH_END
  722. }
  723. #ifndef BOOST_NO_SFINAE
  724. BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
  725. {
  726. this->clear();
  727. return *this;
  728. }
  729. #else
  730. BOOST_FUNCTION_FUNCTION& operator=(int zero)
  731. {
  732. BOOST_ASSERT(zero == 0);
  733. this->clear();
  734. return *this;
  735. }
  736. #endif
  737. // Assignment from another BOOST_FUNCTION_FUNCTION
  738. BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
  739. {
  740. if (&f == this)
  741. return *this;
  742. this->clear();
  743. BOOST_TRY {
  744. this->assign_to_own(f);
  745. } BOOST_CATCH (...) {
  746. vtable = 0;
  747. BOOST_RETHROW;
  748. }
  749. BOOST_CATCH_END
  750. return *this;
  751. }
  752. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  753. // Move assignment from another BOOST_FUNCTION_FUNCTION
  754. BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
  755. {
  756. if (&f == this)
  757. return *this;
  758. this->clear();
  759. BOOST_TRY {
  760. this->move_assign(f);
  761. } BOOST_CATCH (...) {
  762. vtable = 0;
  763. BOOST_RETHROW;
  764. }
  765. BOOST_CATCH_END
  766. return *this;
  767. }
  768. #endif
  769. void swap(BOOST_FUNCTION_FUNCTION& other)
  770. {
  771. if (&other == this)
  772. return;
  773. BOOST_FUNCTION_FUNCTION tmp;
  774. tmp.move_assign(*this);
  775. this->move_assign(other);
  776. other.move_assign(tmp);
  777. }
  778. // Clear out a target, if there is one
  779. void clear()
  780. {
  781. if (vtable) {
  782. if (!this->has_trivial_copy_and_destroy())
  783. get_vtable()->clear(this->functor);
  784. vtable = 0;
  785. }
  786. }
  787. #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
  788. // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
  789. operator bool () const { return !this->empty(); }
  790. #else
  791. private:
  792. struct dummy {
  793. void nonnull() {}
  794. };
  795. typedef void (dummy::*safe_bool)();
  796. public:
  797. operator safe_bool () const
  798. { return (this->empty())? 0 : &dummy::nonnull; }
  799. bool operator!() const
  800. { return this->empty(); }
  801. #endif
  802. private:
  803. void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
  804. {
  805. if (!f.empty()) {
  806. this->vtable = f.vtable;
  807. if (this->has_trivial_copy_and_destroy()) {
  808. // Don't operate on storage directly since union type doesn't relax
  809. // strict aliasing rules, despite of having member char type.
  810. # if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
  811. # pragma GCC diagnostic push
  812. // This warning is technically correct, but we don't want to pay the price for initializing
  813. // just to silence a warning: https://github.com/boostorg/function/issues/27
  814. # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  815. # endif
  816. std::memcpy(this->functor.data, f.functor.data, sizeof(boost::detail::function::function_buffer));
  817. # if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
  818. # pragma GCC diagnostic pop
  819. # endif
  820. } else
  821. get_vtable()->base.manager(f.functor, this->functor,
  822. boost::detail::function::clone_functor_tag);
  823. }
  824. }
  825. template<typename Functor>
  826. void assign_to(Functor f)
  827. {
  828. using boost::detail::function::vtable_base;
  829. typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
  830. typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
  831. typedef typename get_invoker::
  832. template apply<Functor, R BOOST_FUNCTION_COMMA
  833. BOOST_FUNCTION_TEMPLATE_ARGS>
  834. handler_type;
  835. typedef typename handler_type::invoker_type invoker_type;
  836. typedef typename handler_type::manager_type manager_type;
  837. // Note: it is extremely important that this initialization use
  838. // static initialization. Otherwise, we will have a race
  839. // condition here in multi-threaded code. See
  840. // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
  841. static const vtable_type stored_vtable =
  842. { { &manager_type::manage }, &invoker_type::invoke };
  843. if (stored_vtable.assign_to(f, functor)) {
  844. std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
  845. // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
  846. if (boost::has_trivial_copy_constructor<Functor>::value &&
  847. boost::has_trivial_destructor<Functor>::value &&
  848. boost::detail::function::function_allows_small_object_optimization<Functor>::value)
  849. value |= static_cast<std::size_t>(0x01);
  850. vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
  851. } else
  852. vtable = 0;
  853. }
  854. template<typename Functor,typename Allocator>
  855. void assign_to_a(Functor f,Allocator a)
  856. {
  857. using boost::detail::function::vtable_base;
  858. typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
  859. typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
  860. typedef typename get_invoker::
  861. template apply_a<Functor, Allocator, R BOOST_FUNCTION_COMMA
  862. BOOST_FUNCTION_TEMPLATE_ARGS>
  863. handler_type;
  864. typedef typename handler_type::invoker_type invoker_type;
  865. typedef typename handler_type::manager_type manager_type;
  866. // Note: it is extremely important that this initialization use
  867. // static initialization. Otherwise, we will have a race
  868. // condition here in multi-threaded code. See
  869. // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
  870. static const vtable_type stored_vtable =
  871. { { &manager_type::manage }, &invoker_type::invoke };
  872. if (stored_vtable.assign_to_a(f, functor, a)) {
  873. std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
  874. // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
  875. if (boost::has_trivial_copy_constructor<Functor>::value &&
  876. boost::has_trivial_destructor<Functor>::value &&
  877. boost::detail::function::function_allows_small_object_optimization<Functor>::value)
  878. value |= static_cast<std::size_t>(0x01);
  879. vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
  880. } else
  881. vtable = 0;
  882. }
  883. // Moves the value from the specified argument to *this. If the argument
  884. // has its function object allocated on the heap, move_assign will pass
  885. // its buffer to *this, and set the argument's buffer pointer to NULL.
  886. void move_assign(BOOST_FUNCTION_FUNCTION& f)
  887. {
  888. if (&f == this)
  889. return;
  890. BOOST_TRY {
  891. if (!f.empty()) {
  892. this->vtable = f.vtable;
  893. if (this->has_trivial_copy_and_destroy()) {
  894. // Don't operate on storage directly since union type doesn't relax
  895. // strict aliasing rules, despite of having member char type.
  896. # if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
  897. # pragma GCC diagnostic push
  898. // This warning is technically correct, but we don't want to pay the price for initializing
  899. // just to silence a warning: https://github.com/boostorg/function/issues/27
  900. # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  901. # endif
  902. std::memcpy(this->functor.data, f.functor.data, sizeof(this->functor.data));
  903. # if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
  904. # pragma GCC diagnostic pop
  905. # endif
  906. } else
  907. get_vtable()->base.manager(f.functor, this->functor,
  908. boost::detail::function::move_functor_tag);
  909. f.vtable = 0;
  910. } else {
  911. clear();
  912. }
  913. } BOOST_CATCH (...) {
  914. vtable = 0;
  915. BOOST_RETHROW;
  916. }
  917. BOOST_CATCH_END
  918. }
  919. };
  920. template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
  921. inline void swap(BOOST_FUNCTION_FUNCTION<
  922. R BOOST_FUNCTION_COMMA
  923. BOOST_FUNCTION_TEMPLATE_ARGS
  924. >& f1,
  925. BOOST_FUNCTION_FUNCTION<
  926. R BOOST_FUNCTION_COMMA
  927. BOOST_FUNCTION_TEMPLATE_ARGS
  928. >& f2)
  929. {
  930. f1.swap(f2);
  931. }
  932. // Poison comparisons between boost::function objects of the same type.
  933. template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
  934. void operator==(const BOOST_FUNCTION_FUNCTION<
  935. R BOOST_FUNCTION_COMMA
  936. BOOST_FUNCTION_TEMPLATE_ARGS>&,
  937. const BOOST_FUNCTION_FUNCTION<
  938. R BOOST_FUNCTION_COMMA
  939. BOOST_FUNCTION_TEMPLATE_ARGS>&);
  940. template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
  941. void operator!=(const BOOST_FUNCTION_FUNCTION<
  942. R BOOST_FUNCTION_COMMA
  943. BOOST_FUNCTION_TEMPLATE_ARGS>&,
  944. const BOOST_FUNCTION_FUNCTION<
  945. R BOOST_FUNCTION_COMMA
  946. BOOST_FUNCTION_TEMPLATE_ARGS>& );
  947. #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
  948. #if BOOST_FUNCTION_NUM_ARGS == 0
  949. #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
  950. #else
  951. #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_FUNCTION_TEMPLATE_ARGS)
  952. #endif
  953. template<typename R BOOST_FUNCTION_COMMA
  954. BOOST_FUNCTION_TEMPLATE_PARMS>
  955. class function<BOOST_FUNCTION_PARTIAL_SPEC>
  956. : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
  957. {
  958. typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
  959. typedef function self_type;
  960. struct clear_type {};
  961. public:
  962. BOOST_DEFAULTED_FUNCTION(function(), : base_type() {})
  963. template<typename Functor>
  964. function(Functor f
  965. #ifndef BOOST_NO_SFINAE
  966. ,typename boost::enable_if_<
  967. !(is_integral<Functor>::value),
  968. int>::type = 0
  969. #endif
  970. ) :
  971. base_type(f)
  972. {
  973. }
  974. template<typename Functor,typename Allocator>
  975. function(Functor f, Allocator a
  976. #ifndef BOOST_NO_SFINAE
  977. ,typename boost::enable_if_<
  978. !(is_integral<Functor>::value),
  979. int>::type = 0
  980. #endif
  981. ) :
  982. base_type(f,a)
  983. {
  984. }
  985. #ifndef BOOST_NO_SFINAE
  986. function(clear_type*) : base_type() {}
  987. #endif
  988. function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
  989. function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
  990. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  991. // Move constructors
  992. function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
  993. function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
  994. #endif
  995. self_type& operator=(const self_type& f)
  996. {
  997. self_type(f).swap(*this);
  998. return *this;
  999. }
  1000. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  1001. self_type& operator=(self_type&& f)
  1002. {
  1003. self_type(static_cast<self_type&&>(f)).swap(*this);
  1004. return *this;
  1005. }
  1006. #endif
  1007. template<typename Functor>
  1008. #ifndef BOOST_NO_SFINAE
  1009. typename boost::enable_if_<
  1010. !(is_integral<Functor>::value),
  1011. self_type&>::type
  1012. #else
  1013. self_type&
  1014. #endif
  1015. operator=(Functor f)
  1016. {
  1017. self_type(f).swap(*this);
  1018. return *this;
  1019. }
  1020. #ifndef BOOST_NO_SFINAE
  1021. self_type& operator=(clear_type*)
  1022. {
  1023. this->clear();
  1024. return *this;
  1025. }
  1026. #endif
  1027. self_type& operator=(const base_type& f)
  1028. {
  1029. self_type(f).swap(*this);
  1030. return *this;
  1031. }
  1032. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  1033. self_type& operator=(base_type&& f)
  1034. {
  1035. self_type(static_cast<base_type&&>(f)).swap(*this);
  1036. return *this;
  1037. }
  1038. #endif
  1039. };
  1040. #undef BOOST_FUNCTION_PARTIAL_SPEC
  1041. #endif // have partial specialization
  1042. } // end namespace boost
  1043. // Cleanup after ourselves...
  1044. #undef BOOST_FUNCTION_VTABLE
  1045. #undef BOOST_FUNCTION_COMMA
  1046. #undef BOOST_FUNCTION_FUNCTION
  1047. #undef BOOST_FUNCTION_FUNCTION_INVOKER
  1048. #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
  1049. #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
  1050. #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
  1051. #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
  1052. #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
  1053. #undef BOOST_FUNCTION_MEMBER_INVOKER
  1054. #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
  1055. #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
  1056. #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
  1057. #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
  1058. #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
  1059. #undef BOOST_FUNCTION_GET_INVOKER
  1060. #undef BOOST_FUNCTION_TEMPLATE_PARMS
  1061. #undef BOOST_FUNCTION_TEMPLATE_ARGS
  1062. #undef BOOST_FUNCTION_PARMS
  1063. #undef BOOST_FUNCTION_PARM
  1064. #ifdef BOOST_FUNCTION_ARG
  1065. # undef BOOST_FUNCTION_ARG
  1066. #endif
  1067. #undef BOOST_FUNCTION_ARGS
  1068. #undef BOOST_FUNCTION_ARG_TYPE
  1069. #undef BOOST_FUNCTION_ARG_TYPES
  1070. #undef BOOST_FUNCTION_VOID_RETURN_TYPE
  1071. #undef BOOST_FUNCTION_RETURN
  1072. #if defined(BOOST_MSVC)
  1073. # pragma warning( pop )
  1074. #endif