function_base.hpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  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. #ifndef BOOST_FUNCTION_BASE_HEADER
  9. #define BOOST_FUNCTION_BASE_HEADER
  10. #include <stdexcept>
  11. #include <string>
  12. #include <memory>
  13. #include <new>
  14. #include <boost/config.hpp>
  15. #include <boost/assert.hpp>
  16. #include <boost/integer.hpp>
  17. #include <boost/type_index.hpp>
  18. #include <boost/type_traits/has_trivial_copy.hpp>
  19. #include <boost/type_traits/has_trivial_destructor.hpp>
  20. #include <boost/type_traits/is_const.hpp>
  21. #include <boost/type_traits/is_integral.hpp>
  22. #include <boost/type_traits/is_volatile.hpp>
  23. #include <boost/type_traits/composite_traits.hpp>
  24. #include <boost/ref.hpp>
  25. #include <boost/type_traits/conditional.hpp>
  26. #include <boost/config/workaround.hpp>
  27. #include <boost/type_traits/alignment_of.hpp>
  28. #ifndef BOOST_NO_SFINAE
  29. #include <boost/type_traits/enable_if.hpp>
  30. #else
  31. #include <boost/type_traits/integral_constant.hpp>
  32. #endif
  33. #include <boost/function_equal.hpp>
  34. #include <boost/function/function_fwd.hpp>
  35. #if defined(BOOST_MSVC)
  36. # pragma warning( push )
  37. # pragma warning( disable : 4793 ) // complaint about native code generation
  38. # pragma warning( disable : 4127 ) // "conditional expression is constant"
  39. #endif
  40. #if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
  41. # define BOOST_FUNCTION_TARGET_FIX(x) x
  42. #else
  43. # define BOOST_FUNCTION_TARGET_FIX(x)
  44. #endif // __ICL etc
  45. # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
  46. typename ::boost::enable_if_< \
  47. !(::boost::is_integral<Functor>::value), \
  48. Type>::type
  49. namespace boost {
  50. namespace detail {
  51. namespace function {
  52. class X;
  53. /**
  54. * A buffer used to store small function objects in
  55. * boost::function. It is a union containing function pointers,
  56. * object pointers, and a structure that resembles a bound
  57. * member function pointer.
  58. */
  59. union function_buffer_members
  60. {
  61. // For pointers to function objects
  62. typedef void* obj_ptr_t;
  63. mutable obj_ptr_t obj_ptr;
  64. // For pointers to std::type_info objects
  65. struct type_t {
  66. // (get_functor_type_tag, check_functor_type_tag).
  67. const boost::typeindex::type_info* type;
  68. // Whether the type is const-qualified.
  69. bool const_qualified;
  70. // Whether the type is volatile-qualified.
  71. bool volatile_qualified;
  72. } type;
  73. // For function pointers of all kinds
  74. typedef void (*func_ptr_t)();
  75. mutable func_ptr_t func_ptr;
  76. // For bound member pointers
  77. struct bound_memfunc_ptr_t {
  78. void (X::*memfunc_ptr)(int);
  79. void* obj_ptr;
  80. } bound_memfunc_ptr;
  81. // For references to function objects. We explicitly keep
  82. // track of the cv-qualifiers on the object referenced.
  83. struct obj_ref_t {
  84. mutable void* obj_ptr;
  85. bool is_const_qualified;
  86. bool is_volatile_qualified;
  87. } obj_ref;
  88. };
  89. union BOOST_SYMBOL_VISIBLE function_buffer
  90. {
  91. // Type-specific union members
  92. mutable function_buffer_members members;
  93. // To relax aliasing constraints
  94. mutable char data[sizeof(function_buffer_members)];
  95. };
  96. /**
  97. * The unusable class is a placeholder for unused function arguments
  98. * It is also completely unusable except that it constructable from
  99. * anything. This helps compilers without partial specialization to
  100. * handle Boost.Function objects returning void.
  101. */
  102. struct unusable
  103. {
  104. unusable() {}
  105. template<typename T> unusable(const T&) {}
  106. };
  107. /* Determine the return type. This supports compilers that do not support
  108. * void returns or partial specialization by silently changing the return
  109. * type to "unusable".
  110. */
  111. template<typename T> struct function_return_type { typedef T type; };
  112. template<>
  113. struct function_return_type<void>
  114. {
  115. typedef unusable type;
  116. };
  117. // The operation type to perform on the given functor/function pointer
  118. enum functor_manager_operation_type {
  119. clone_functor_tag,
  120. move_functor_tag,
  121. destroy_functor_tag,
  122. check_functor_type_tag,
  123. get_functor_type_tag
  124. };
  125. // Tags used to decide between different types of functions
  126. struct function_ptr_tag {};
  127. struct function_obj_tag {};
  128. struct member_ptr_tag {};
  129. struct function_obj_ref_tag {};
  130. template<typename F>
  131. class get_function_tag
  132. {
  133. typedef typename conditional<(is_pointer<F>::value),
  134. function_ptr_tag,
  135. function_obj_tag>::type ptr_or_obj_tag;
  136. typedef typename conditional<(is_member_pointer<F>::value),
  137. member_ptr_tag,
  138. ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
  139. typedef typename conditional<(is_reference_wrapper<F>::value),
  140. function_obj_ref_tag,
  141. ptr_or_obj_or_mem_tag>::type or_ref_tag;
  142. public:
  143. typedef or_ref_tag type;
  144. };
  145. // The trivial manager does nothing but return the same pointer (if we
  146. // are cloning) or return the null pointer (if we are deleting).
  147. template<typename F>
  148. struct reference_manager
  149. {
  150. static inline void
  151. manage(const function_buffer& in_buffer, function_buffer& out_buffer,
  152. functor_manager_operation_type op)
  153. {
  154. switch (op) {
  155. case clone_functor_tag:
  156. out_buffer.members.obj_ref = in_buffer.members.obj_ref;
  157. return;
  158. case move_functor_tag:
  159. out_buffer.members.obj_ref = in_buffer.members.obj_ref;
  160. in_buffer.members.obj_ref.obj_ptr = 0;
  161. return;
  162. case destroy_functor_tag:
  163. out_buffer.members.obj_ref.obj_ptr = 0;
  164. return;
  165. case check_functor_type_tag:
  166. {
  167. // Check whether we have the same type. We can add
  168. // cv-qualifiers, but we can't take them away.
  169. if (*out_buffer.members.type.type == boost::typeindex::type_id<F>()
  170. && (!in_buffer.members.obj_ref.is_const_qualified
  171. || out_buffer.members.type.const_qualified)
  172. && (!in_buffer.members.obj_ref.is_volatile_qualified
  173. || out_buffer.members.type.volatile_qualified))
  174. out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
  175. else
  176. out_buffer.members.obj_ptr = 0;
  177. }
  178. return;
  179. case get_functor_type_tag:
  180. out_buffer.members.type.type = &boost::typeindex::type_id<F>().type_info();
  181. out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
  182. out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
  183. return;
  184. }
  185. }
  186. };
  187. /**
  188. * Determine if boost::function can use the small-object
  189. * optimization with the function object type F.
  190. */
  191. template<typename F>
  192. struct function_allows_small_object_optimization
  193. {
  194. BOOST_STATIC_CONSTANT
  195. (bool,
  196. value = ((sizeof(F) <= sizeof(function_buffer) &&
  197. (alignment_of<function_buffer>::value
  198. % alignment_of<F>::value == 0))));
  199. };
  200. template <typename F,typename A>
  201. struct functor_wrapper: public F, public A
  202. {
  203. functor_wrapper( F f, A a ):
  204. F(f),
  205. A(a)
  206. {
  207. }
  208. functor_wrapper(const functor_wrapper& f) :
  209. F(static_cast<const F&>(f)),
  210. A(static_cast<const A&>(f))
  211. {
  212. }
  213. };
  214. /**
  215. * The functor_manager class contains a static function "manage" which
  216. * can clone or destroy the given function/function object pointer.
  217. */
  218. template<typename Functor>
  219. struct functor_manager_common
  220. {
  221. typedef Functor functor_type;
  222. // Function pointers
  223. static inline void
  224. manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
  225. functor_manager_operation_type op)
  226. {
  227. if (op == clone_functor_tag)
  228. out_buffer.members.func_ptr = in_buffer.members.func_ptr;
  229. else if (op == move_functor_tag) {
  230. out_buffer.members.func_ptr = in_buffer.members.func_ptr;
  231. in_buffer.members.func_ptr = 0;
  232. } else if (op == destroy_functor_tag)
  233. out_buffer.members.func_ptr = 0;
  234. else if (op == check_functor_type_tag) {
  235. if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
  236. out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
  237. else
  238. out_buffer.members.obj_ptr = 0;
  239. } else /* op == get_functor_type_tag */ {
  240. out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
  241. out_buffer.members.type.const_qualified = false;
  242. out_buffer.members.type.volatile_qualified = false;
  243. }
  244. }
  245. // Function objects that fit in the small-object buffer.
  246. static inline void
  247. manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
  248. functor_manager_operation_type op)
  249. {
  250. if (op == clone_functor_tag || op == move_functor_tag) {
  251. const functor_type* in_functor =
  252. reinterpret_cast<const functor_type*>(in_buffer.data);
  253. new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
  254. if (op == move_functor_tag) {
  255. functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
  256. (void)f; // suppress warning about the value of f not being used (MSVC)
  257. f->~Functor();
  258. }
  259. } else if (op == destroy_functor_tag) {
  260. // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
  261. functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data);
  262. (void)f; // suppress warning about the value of f not being used (MSVC)
  263. f->~Functor();
  264. } else if (op == check_functor_type_tag) {
  265. if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
  266. out_buffer.members.obj_ptr = in_buffer.data;
  267. else
  268. out_buffer.members.obj_ptr = 0;
  269. } else /* op == get_functor_type_tag */ {
  270. out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
  271. out_buffer.members.type.const_qualified = false;
  272. out_buffer.members.type.volatile_qualified = false;
  273. }
  274. }
  275. };
  276. template<typename Functor>
  277. struct functor_manager
  278. {
  279. private:
  280. typedef Functor functor_type;
  281. // Function pointers
  282. static inline void
  283. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  284. functor_manager_operation_type op, function_ptr_tag)
  285. {
  286. functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
  287. }
  288. // Function objects that fit in the small-object buffer.
  289. static inline void
  290. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  291. functor_manager_operation_type op, true_type)
  292. {
  293. functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
  294. }
  295. // Function objects that require heap allocation
  296. static inline void
  297. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  298. functor_manager_operation_type op, false_type)
  299. {
  300. if (op == clone_functor_tag) {
  301. // Clone the functor
  302. // GCC 2.95.3 gets the CV qualifiers wrong here, so we
  303. // can't do the static_cast that we should do.
  304. // jewillco: Changing this to static_cast because GCC 2.95.3 is
  305. // obsolete.
  306. const functor_type* f =
  307. static_cast<const functor_type*>(in_buffer.members.obj_ptr);
  308. functor_type* new_f = new functor_type(*f);
  309. out_buffer.members.obj_ptr = new_f;
  310. } else if (op == move_functor_tag) {
  311. out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
  312. in_buffer.members.obj_ptr = 0;
  313. } else if (op == destroy_functor_tag) {
  314. /* Cast from the void pointer to the functor pointer type */
  315. functor_type* f =
  316. static_cast<functor_type*>(out_buffer.members.obj_ptr);
  317. delete f;
  318. out_buffer.members.obj_ptr = 0;
  319. } else if (op == check_functor_type_tag) {
  320. if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
  321. out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
  322. else
  323. out_buffer.members.obj_ptr = 0;
  324. } else /* op == get_functor_type_tag */ {
  325. out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
  326. out_buffer.members.type.const_qualified = false;
  327. out_buffer.members.type.volatile_qualified = false;
  328. }
  329. }
  330. // For function objects, we determine whether the function
  331. // object can use the small-object optimization buffer or
  332. // whether we need to allocate it on the heap.
  333. static inline void
  334. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  335. functor_manager_operation_type op, function_obj_tag)
  336. {
  337. manager(in_buffer, out_buffer, op,
  338. integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
  339. }
  340. // For member pointers, we use the small-object optimization buffer.
  341. static inline void
  342. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  343. functor_manager_operation_type op, member_ptr_tag)
  344. {
  345. manager(in_buffer, out_buffer, op, true_type());
  346. }
  347. public:
  348. /* Dispatch to an appropriate manager based on whether we have a
  349. function pointer or a function object pointer. */
  350. static inline void
  351. manage(const function_buffer& in_buffer, function_buffer& out_buffer,
  352. functor_manager_operation_type op)
  353. {
  354. typedef typename get_function_tag<functor_type>::type tag_type;
  355. if (op == get_functor_type_tag) {
  356. out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
  357. out_buffer.members.type.const_qualified = false;
  358. out_buffer.members.type.volatile_qualified = false;
  359. } else {
  360. manager(in_buffer, out_buffer, op, tag_type());
  361. }
  362. }
  363. };
  364. template<typename Functor, typename Allocator>
  365. struct functor_manager_a
  366. {
  367. private:
  368. typedef Functor functor_type;
  369. // Function pointers
  370. static inline void
  371. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  372. functor_manager_operation_type op, function_ptr_tag)
  373. {
  374. functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
  375. }
  376. // Function objects that fit in the small-object buffer.
  377. static inline void
  378. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  379. functor_manager_operation_type op, true_type)
  380. {
  381. functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
  382. }
  383. // Function objects that require heap allocation
  384. static inline void
  385. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  386. functor_manager_operation_type op, false_type)
  387. {
  388. typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
  389. #if defined(BOOST_NO_CXX11_ALLOCATOR)
  390. typedef typename Allocator::template rebind<functor_wrapper_type>::other
  391. wrapper_allocator_type;
  392. typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
  393. #else
  394. using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
  395. using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
  396. #endif
  397. if (op == clone_functor_tag) {
  398. // Clone the functor
  399. // GCC 2.95.3 gets the CV qualifiers wrong here, so we
  400. // can't do the static_cast that we should do.
  401. const functor_wrapper_type* f =
  402. static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
  403. wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
  404. wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
  405. #if defined(BOOST_NO_CXX11_ALLOCATOR)
  406. wrapper_allocator.construct(copy, *f);
  407. #else
  408. std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, *f);
  409. #endif
  410. // Get back to the original pointer type
  411. functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
  412. out_buffer.members.obj_ptr = new_f;
  413. } else if (op == move_functor_tag) {
  414. out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
  415. in_buffer.members.obj_ptr = 0;
  416. } else if (op == destroy_functor_tag) {
  417. /* Cast from the void pointer to the functor_wrapper_type */
  418. functor_wrapper_type* victim =
  419. static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
  420. wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
  421. #if defined(BOOST_NO_CXX11_ALLOCATOR)
  422. wrapper_allocator.destroy(victim);
  423. #else
  424. std::allocator_traits<wrapper_allocator_type>::destroy(wrapper_allocator, victim);
  425. #endif
  426. wrapper_allocator.deallocate(victim,1);
  427. out_buffer.members.obj_ptr = 0;
  428. } else if (op == check_functor_type_tag) {
  429. if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
  430. out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
  431. else
  432. out_buffer.members.obj_ptr = 0;
  433. } else /* op == get_functor_type_tag */ {
  434. out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
  435. out_buffer.members.type.const_qualified = false;
  436. out_buffer.members.type.volatile_qualified = false;
  437. }
  438. }
  439. // For function objects, we determine whether the function
  440. // object can use the small-object optimization buffer or
  441. // whether we need to allocate it on the heap.
  442. static inline void
  443. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  444. functor_manager_operation_type op, function_obj_tag)
  445. {
  446. manager(in_buffer, out_buffer, op,
  447. integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
  448. }
  449. public:
  450. /* Dispatch to an appropriate manager based on whether we have a
  451. function pointer or a function object pointer. */
  452. static inline void
  453. manage(const function_buffer& in_buffer, function_buffer& out_buffer,
  454. functor_manager_operation_type op)
  455. {
  456. typedef typename get_function_tag<functor_type>::type tag_type;
  457. if (op == get_functor_type_tag) {
  458. out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
  459. out_buffer.members.type.const_qualified = false;
  460. out_buffer.members.type.volatile_qualified = false;
  461. } else {
  462. manager(in_buffer, out_buffer, op, tag_type());
  463. }
  464. }
  465. };
  466. // A type that is only used for comparisons against zero
  467. struct useless_clear_type {};
  468. #ifdef BOOST_NO_SFINAE
  469. // These routines perform comparisons between a Boost.Function
  470. // object and an arbitrary function object (when the last
  471. // parameter is false_type) or against zero (when the
  472. // last parameter is true_type). They are only necessary
  473. // for compilers that don't support SFINAE.
  474. template<typename Function, typename Functor>
  475. bool
  476. compare_equal(const Function& f, const Functor&, int, true_type)
  477. { return f.empty(); }
  478. template<typename Function, typename Functor>
  479. bool
  480. compare_not_equal(const Function& f, const Functor&, int,
  481. true_type)
  482. { return !f.empty(); }
  483. template<typename Function, typename Functor>
  484. bool
  485. compare_equal(const Function& f, const Functor& g, long,
  486. false_type)
  487. {
  488. if (const Functor* fp = f.template target<Functor>())
  489. return function_equal(*fp, g);
  490. else return false;
  491. }
  492. template<typename Function, typename Functor>
  493. bool
  494. compare_equal(const Function& f, const reference_wrapper<Functor>& g,
  495. int, false_type)
  496. {
  497. if (const Functor* fp = f.template target<Functor>())
  498. return fp == g.get_pointer();
  499. else return false;
  500. }
  501. template<typename Function, typename Functor>
  502. bool
  503. compare_not_equal(const Function& f, const Functor& g, long,
  504. false_type)
  505. {
  506. if (const Functor* fp = f.template target<Functor>())
  507. return !function_equal(*fp, g);
  508. else return true;
  509. }
  510. template<typename Function, typename Functor>
  511. bool
  512. compare_not_equal(const Function& f,
  513. const reference_wrapper<Functor>& g, int,
  514. false_type)
  515. {
  516. if (const Functor* fp = f.template target<Functor>())
  517. return fp != g.get_pointer();
  518. else return true;
  519. }
  520. #endif // BOOST_NO_SFINAE
  521. /**
  522. * Stores the "manager" portion of the vtable for a
  523. * boost::function object.
  524. */
  525. struct vtable_base
  526. {
  527. void (*manager)(const function_buffer& in_buffer,
  528. function_buffer& out_buffer,
  529. functor_manager_operation_type op);
  530. };
  531. } // end namespace function
  532. } // end namespace detail
  533. /**
  534. * The function_base class contains the basic elements needed for the
  535. * function1, function2, function3, etc. classes. It is common to all
  536. * functions (and as such can be used to tell if we have one of the
  537. * functionN objects).
  538. */
  539. class function_base
  540. {
  541. public:
  542. function_base() : vtable(0) { }
  543. /** Determine if the function is empty (i.e., has no target). */
  544. bool empty() const { return !vtable; }
  545. /** Retrieve the type of the stored function object, or type_id<void>()
  546. if this is empty. */
  547. const boost::typeindex::type_info& target_type() const
  548. {
  549. if (!vtable) return boost::typeindex::type_id<void>().type_info();
  550. detail::function::function_buffer type;
  551. get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
  552. return *type.members.type.type;
  553. }
  554. template<typename Functor>
  555. Functor* target()
  556. {
  557. if (!vtable) return 0;
  558. detail::function::function_buffer type_result;
  559. type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
  560. type_result.members.type.const_qualified = is_const<Functor>::value;
  561. type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
  562. get_vtable()->manager(functor, type_result,
  563. detail::function::check_functor_type_tag);
  564. return static_cast<Functor*>(type_result.members.obj_ptr);
  565. }
  566. template<typename Functor>
  567. const Functor* target() const
  568. {
  569. if (!vtable) return 0;
  570. detail::function::function_buffer type_result;
  571. type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
  572. type_result.members.type.const_qualified = true;
  573. type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
  574. get_vtable()->manager(functor, type_result,
  575. detail::function::check_functor_type_tag);
  576. // GCC 2.95.3 gets the CV qualifiers wrong here, so we
  577. // can't do the static_cast that we should do.
  578. return static_cast<const Functor*>(type_result.members.obj_ptr);
  579. }
  580. template<typename F>
  581. bool contains(const F& f) const
  582. {
  583. if (const F* fp = this->template target<F>())
  584. {
  585. return function_equal(*fp, f);
  586. } else {
  587. return false;
  588. }
  589. }
  590. #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
  591. // GCC 3.3 and newer cannot copy with the global operator==, due to
  592. // problems with instantiation of function return types before it
  593. // has been verified that the argument types match up.
  594. template<typename Functor>
  595. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  596. operator==(Functor g) const
  597. {
  598. if (const Functor* fp = target<Functor>())
  599. return function_equal(*fp, g);
  600. else return false;
  601. }
  602. template<typename Functor>
  603. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  604. operator!=(Functor g) const
  605. {
  606. if (const Functor* fp = target<Functor>())
  607. return !function_equal(*fp, g);
  608. else return true;
  609. }
  610. #endif
  611. public: // should be protected, but GCC 2.95.3 will fail to allow access
  612. detail::function::vtable_base* get_vtable() const {
  613. return reinterpret_cast<detail::function::vtable_base*>(
  614. reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
  615. }
  616. bool has_trivial_copy_and_destroy() const {
  617. return reinterpret_cast<std::size_t>(vtable) & 0x01;
  618. }
  619. detail::function::vtable_base* vtable;
  620. mutable detail::function::function_buffer functor;
  621. };
  622. #if defined(BOOST_CLANG)
  623. # pragma clang diagnostic push
  624. # pragma clang diagnostic ignored "-Wweak-vtables"
  625. #endif
  626. /**
  627. * The bad_function_call exception class is thrown when a boost::function
  628. * object is invoked
  629. */
  630. class BOOST_SYMBOL_VISIBLE bad_function_call : public std::runtime_error
  631. {
  632. public:
  633. bad_function_call() : std::runtime_error("call to empty boost::function") {}
  634. };
  635. #if defined(BOOST_CLANG)
  636. # pragma clang diagnostic pop
  637. #endif
  638. #ifndef BOOST_NO_SFINAE
  639. inline bool operator==(const function_base& f,
  640. detail::function::useless_clear_type*)
  641. {
  642. return f.empty();
  643. }
  644. inline bool operator!=(const function_base& f,
  645. detail::function::useless_clear_type*)
  646. {
  647. return !f.empty();
  648. }
  649. inline bool operator==(detail::function::useless_clear_type*,
  650. const function_base& f)
  651. {
  652. return f.empty();
  653. }
  654. inline bool operator!=(detail::function::useless_clear_type*,
  655. const function_base& f)
  656. {
  657. return !f.empty();
  658. }
  659. #endif
  660. #ifdef BOOST_NO_SFINAE
  661. // Comparisons between boost::function objects and arbitrary function objects
  662. template<typename Functor>
  663. inline bool operator==(const function_base& f, Functor g)
  664. {
  665. typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
  666. return detail::function::compare_equal(f, g, 0, integral());
  667. }
  668. template<typename Functor>
  669. inline bool operator==(Functor g, const function_base& f)
  670. {
  671. typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
  672. return detail::function::compare_equal(f, g, 0, integral());
  673. }
  674. template<typename Functor>
  675. inline bool operator!=(const function_base& f, Functor g)
  676. {
  677. typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
  678. return detail::function::compare_not_equal(f, g, 0, integral());
  679. }
  680. template<typename Functor>
  681. inline bool operator!=(Functor g, const function_base& f)
  682. {
  683. typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
  684. return detail::function::compare_not_equal(f, g, 0, integral());
  685. }
  686. #else
  687. # if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
  688. // Comparisons between boost::function objects and arbitrary function
  689. // objects. GCC 3.3 and before has an obnoxious bug that prevents this
  690. // from working.
  691. template<typename Functor>
  692. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  693. operator==(const function_base& f, Functor g)
  694. {
  695. if (const Functor* fp = f.template target<Functor>())
  696. return function_equal(*fp, g);
  697. else return false;
  698. }
  699. template<typename Functor>
  700. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  701. operator==(Functor g, const function_base& f)
  702. {
  703. if (const Functor* fp = f.template target<Functor>())
  704. return function_equal(g, *fp);
  705. else return false;
  706. }
  707. template<typename Functor>
  708. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  709. operator!=(const function_base& f, Functor g)
  710. {
  711. if (const Functor* fp = f.template target<Functor>())
  712. return !function_equal(*fp, g);
  713. else return true;
  714. }
  715. template<typename Functor>
  716. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  717. operator!=(Functor g, const function_base& f)
  718. {
  719. if (const Functor* fp = f.template target<Functor>())
  720. return !function_equal(g, *fp);
  721. else return true;
  722. }
  723. # endif
  724. template<typename Functor>
  725. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  726. operator==(const function_base& f, reference_wrapper<Functor> g)
  727. {
  728. if (const Functor* fp = f.template target<Functor>())
  729. return fp == g.get_pointer();
  730. else return false;
  731. }
  732. template<typename Functor>
  733. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  734. operator==(reference_wrapper<Functor> g, const function_base& f)
  735. {
  736. if (const Functor* fp = f.template target<Functor>())
  737. return g.get_pointer() == fp;
  738. else return false;
  739. }
  740. template<typename Functor>
  741. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  742. operator!=(const function_base& f, reference_wrapper<Functor> g)
  743. {
  744. if (const Functor* fp = f.template target<Functor>())
  745. return fp != g.get_pointer();
  746. else return true;
  747. }
  748. template<typename Functor>
  749. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  750. operator!=(reference_wrapper<Functor> g, const function_base& f)
  751. {
  752. if (const Functor* fp = f.template target<Functor>())
  753. return g.get_pointer() != fp;
  754. else return true;
  755. }
  756. #endif // Compiler supporting SFINAE
  757. namespace detail {
  758. namespace function {
  759. inline bool has_empty_target(const function_base* f)
  760. {
  761. return f->empty();
  762. }
  763. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
  764. inline bool has_empty_target(const void*)
  765. {
  766. return false;
  767. }
  768. #else
  769. inline bool has_empty_target(...)
  770. {
  771. return false;
  772. }
  773. #endif
  774. } // end namespace function
  775. } // end namespace detail
  776. } // end namespace boost
  777. #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
  778. #if defined(BOOST_MSVC)
  779. # pragma warning( pop )
  780. #endif
  781. #endif // BOOST_FUNCTION_BASE_HEADER