function_base.hpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  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. switch (op) {
  356. case get_functor_type_tag:
  357. out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
  358. out_buffer.members.type.const_qualified = false;
  359. out_buffer.members.type.volatile_qualified = false;
  360. return;
  361. default:
  362. manager(in_buffer, out_buffer, op, tag_type());
  363. return;
  364. }
  365. }
  366. };
  367. template<typename Functor, typename Allocator>
  368. struct functor_manager_a
  369. {
  370. private:
  371. typedef Functor functor_type;
  372. // Function pointers
  373. static inline void
  374. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  375. functor_manager_operation_type op, function_ptr_tag)
  376. {
  377. functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
  378. }
  379. // Function objects that fit in the small-object buffer.
  380. static inline void
  381. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  382. functor_manager_operation_type op, true_type)
  383. {
  384. functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
  385. }
  386. // Function objects that require heap allocation
  387. static inline void
  388. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  389. functor_manager_operation_type op, false_type)
  390. {
  391. typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
  392. #if defined(BOOST_NO_CXX11_ALLOCATOR)
  393. typedef typename Allocator::template rebind<functor_wrapper_type>::other
  394. wrapper_allocator_type;
  395. typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
  396. #else
  397. using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
  398. using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
  399. #endif
  400. if (op == clone_functor_tag) {
  401. // Clone the functor
  402. // GCC 2.95.3 gets the CV qualifiers wrong here, so we
  403. // can't do the static_cast that we should do.
  404. const functor_wrapper_type* f =
  405. static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
  406. wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
  407. wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
  408. #if defined(BOOST_NO_CXX11_ALLOCATOR)
  409. wrapper_allocator.construct(copy, *f);
  410. #else
  411. std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, *f);
  412. #endif
  413. // Get back to the original pointer type
  414. functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
  415. out_buffer.members.obj_ptr = new_f;
  416. } else if (op == move_functor_tag) {
  417. out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
  418. in_buffer.members.obj_ptr = 0;
  419. } else if (op == destroy_functor_tag) {
  420. /* Cast from the void pointer to the functor_wrapper_type */
  421. functor_wrapper_type* victim =
  422. static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
  423. wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
  424. #if defined(BOOST_NO_CXX11_ALLOCATOR)
  425. wrapper_allocator.destroy(victim);
  426. #else
  427. std::allocator_traits<wrapper_allocator_type>::destroy(wrapper_allocator, victim);
  428. #endif
  429. wrapper_allocator.deallocate(victim,1);
  430. out_buffer.members.obj_ptr = 0;
  431. } else if (op == check_functor_type_tag) {
  432. if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
  433. out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
  434. else
  435. out_buffer.members.obj_ptr = 0;
  436. } else /* op == get_functor_type_tag */ {
  437. out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
  438. out_buffer.members.type.const_qualified = false;
  439. out_buffer.members.type.volatile_qualified = false;
  440. }
  441. }
  442. // For function objects, we determine whether the function
  443. // object can use the small-object optimization buffer or
  444. // whether we need to allocate it on the heap.
  445. static inline void
  446. manager(const function_buffer& in_buffer, function_buffer& out_buffer,
  447. functor_manager_operation_type op, function_obj_tag)
  448. {
  449. manager(in_buffer, out_buffer, op,
  450. integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
  451. }
  452. public:
  453. /* Dispatch to an appropriate manager based on whether we have a
  454. function pointer or a function object pointer. */
  455. static inline void
  456. manage(const function_buffer& in_buffer, function_buffer& out_buffer,
  457. functor_manager_operation_type op)
  458. {
  459. typedef typename get_function_tag<functor_type>::type tag_type;
  460. switch (op) {
  461. case get_functor_type_tag:
  462. out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
  463. out_buffer.members.type.const_qualified = false;
  464. out_buffer.members.type.volatile_qualified = false;
  465. return;
  466. default:
  467. manager(in_buffer, out_buffer, op, tag_type());
  468. return;
  469. }
  470. }
  471. };
  472. // A type that is only used for comparisons against zero
  473. struct useless_clear_type {};
  474. #ifdef BOOST_NO_SFINAE
  475. // These routines perform comparisons between a Boost.Function
  476. // object and an arbitrary function object (when the last
  477. // parameter is false_type) or against zero (when the
  478. // last parameter is true_type). They are only necessary
  479. // for compilers that don't support SFINAE.
  480. template<typename Function, typename Functor>
  481. bool
  482. compare_equal(const Function& f, const Functor&, int, true_type)
  483. { return f.empty(); }
  484. template<typename Function, typename Functor>
  485. bool
  486. compare_not_equal(const Function& f, const Functor&, int,
  487. true_type)
  488. { return !f.empty(); }
  489. template<typename Function, typename Functor>
  490. bool
  491. compare_equal(const Function& f, const Functor& g, long,
  492. false_type)
  493. {
  494. if (const Functor* fp = f.template target<Functor>())
  495. return function_equal(*fp, g);
  496. else return false;
  497. }
  498. template<typename Function, typename Functor>
  499. bool
  500. compare_equal(const Function& f, const reference_wrapper<Functor>& g,
  501. int, false_type)
  502. {
  503. if (const Functor* fp = f.template target<Functor>())
  504. return fp == g.get_pointer();
  505. else return false;
  506. }
  507. template<typename Function, typename Functor>
  508. bool
  509. compare_not_equal(const Function& f, const Functor& g, long,
  510. false_type)
  511. {
  512. if (const Functor* fp = f.template target<Functor>())
  513. return !function_equal(*fp, g);
  514. else return true;
  515. }
  516. template<typename Function, typename Functor>
  517. bool
  518. compare_not_equal(const Function& f,
  519. const reference_wrapper<Functor>& g, int,
  520. false_type)
  521. {
  522. if (const Functor* fp = f.template target<Functor>())
  523. return fp != g.get_pointer();
  524. else return true;
  525. }
  526. #endif // BOOST_NO_SFINAE
  527. /**
  528. * Stores the "manager" portion of the vtable for a
  529. * boost::function object.
  530. */
  531. struct vtable_base
  532. {
  533. void (*manager)(const function_buffer& in_buffer,
  534. function_buffer& out_buffer,
  535. functor_manager_operation_type op);
  536. };
  537. } // end namespace function
  538. } // end namespace detail
  539. /**
  540. * The function_base class contains the basic elements needed for the
  541. * function1, function2, function3, etc. classes. It is common to all
  542. * functions (and as such can be used to tell if we have one of the
  543. * functionN objects).
  544. */
  545. class function_base
  546. {
  547. public:
  548. function_base() : vtable(0) { }
  549. /** Determine if the function is empty (i.e., has no target). */
  550. bool empty() const { return !vtable; }
  551. /** Retrieve the type of the stored function object, or type_id<void>()
  552. if this is empty. */
  553. const boost::typeindex::type_info& target_type() const
  554. {
  555. if (!vtable) return boost::typeindex::type_id<void>().type_info();
  556. detail::function::function_buffer type;
  557. get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
  558. return *type.members.type.type;
  559. }
  560. template<typename Functor>
  561. Functor* target()
  562. {
  563. if (!vtable) return 0;
  564. detail::function::function_buffer type_result;
  565. type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
  566. type_result.members.type.const_qualified = is_const<Functor>::value;
  567. type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
  568. get_vtable()->manager(functor, type_result,
  569. detail::function::check_functor_type_tag);
  570. return static_cast<Functor*>(type_result.members.obj_ptr);
  571. }
  572. template<typename Functor>
  573. const Functor* target() const
  574. {
  575. if (!vtable) return 0;
  576. detail::function::function_buffer type_result;
  577. type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
  578. type_result.members.type.const_qualified = true;
  579. type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
  580. get_vtable()->manager(functor, type_result,
  581. detail::function::check_functor_type_tag);
  582. // GCC 2.95.3 gets the CV qualifiers wrong here, so we
  583. // can't do the static_cast that we should do.
  584. return static_cast<const Functor*>(type_result.members.obj_ptr);
  585. }
  586. template<typename F>
  587. bool contains(const F& f) const
  588. {
  589. if (const F* fp = this->template target<F>())
  590. {
  591. return function_equal(*fp, f);
  592. } else {
  593. return false;
  594. }
  595. }
  596. #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
  597. // GCC 3.3 and newer cannot copy with the global operator==, due to
  598. // problems with instantiation of function return types before it
  599. // has been verified that the argument types match up.
  600. template<typename Functor>
  601. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  602. operator==(Functor g) const
  603. {
  604. if (const Functor* fp = target<Functor>())
  605. return function_equal(*fp, g);
  606. else return false;
  607. }
  608. template<typename Functor>
  609. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  610. operator!=(Functor g) const
  611. {
  612. if (const Functor* fp = target<Functor>())
  613. return !function_equal(*fp, g);
  614. else return true;
  615. }
  616. #endif
  617. public: // should be protected, but GCC 2.95.3 will fail to allow access
  618. detail::function::vtable_base* get_vtable() const {
  619. return reinterpret_cast<detail::function::vtable_base*>(
  620. reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
  621. }
  622. bool has_trivial_copy_and_destroy() const {
  623. return reinterpret_cast<std::size_t>(vtable) & 0x01;
  624. }
  625. detail::function::vtable_base* vtable;
  626. mutable detail::function::function_buffer functor;
  627. };
  628. #if defined(BOOST_CLANG)
  629. # pragma clang diagnostic push
  630. # pragma clang diagnostic ignored "-Wweak-vtables"
  631. #endif
  632. /**
  633. * The bad_function_call exception class is thrown when a boost::function
  634. * object is invoked
  635. */
  636. class BOOST_SYMBOL_VISIBLE bad_function_call : public std::runtime_error
  637. {
  638. public:
  639. bad_function_call() : std::runtime_error("call to empty boost::function") {}
  640. };
  641. #if defined(BOOST_CLANG)
  642. # pragma clang diagnostic pop
  643. #endif
  644. #ifndef BOOST_NO_SFINAE
  645. inline bool operator==(const function_base& f,
  646. detail::function::useless_clear_type*)
  647. {
  648. return f.empty();
  649. }
  650. inline bool operator!=(const function_base& f,
  651. detail::function::useless_clear_type*)
  652. {
  653. return !f.empty();
  654. }
  655. inline bool operator==(detail::function::useless_clear_type*,
  656. const function_base& f)
  657. {
  658. return f.empty();
  659. }
  660. inline bool operator!=(detail::function::useless_clear_type*,
  661. const function_base& f)
  662. {
  663. return !f.empty();
  664. }
  665. #endif
  666. #ifdef BOOST_NO_SFINAE
  667. // Comparisons between boost::function objects and arbitrary function objects
  668. template<typename Functor>
  669. inline bool operator==(const function_base& f, Functor g)
  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==(Functor g, const function_base& f)
  676. {
  677. typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
  678. return detail::function::compare_equal(f, g, 0, integral());
  679. }
  680. template<typename Functor>
  681. inline bool operator!=(const function_base& f, Functor g)
  682. {
  683. typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
  684. return detail::function::compare_not_equal(f, g, 0, integral());
  685. }
  686. template<typename Functor>
  687. inline bool operator!=(Functor g, const function_base& f)
  688. {
  689. typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
  690. return detail::function::compare_not_equal(f, g, 0, integral());
  691. }
  692. #else
  693. # if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
  694. // Comparisons between boost::function objects and arbitrary function
  695. // objects. GCC 3.3 and before has an obnoxious bug that prevents this
  696. // from working.
  697. template<typename Functor>
  698. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  699. operator==(const function_base& f, Functor g)
  700. {
  701. if (const Functor* fp = f.template target<Functor>())
  702. return function_equal(*fp, g);
  703. else return false;
  704. }
  705. template<typename Functor>
  706. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  707. operator==(Functor g, const function_base& f)
  708. {
  709. if (const Functor* fp = f.template target<Functor>())
  710. return function_equal(g, *fp);
  711. else return false;
  712. }
  713. template<typename Functor>
  714. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  715. operator!=(const function_base& f, Functor g)
  716. {
  717. if (const Functor* fp = f.template target<Functor>())
  718. return !function_equal(*fp, g);
  719. else return true;
  720. }
  721. template<typename Functor>
  722. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  723. operator!=(Functor g, const function_base& f)
  724. {
  725. if (const Functor* fp = f.template target<Functor>())
  726. return !function_equal(g, *fp);
  727. else return true;
  728. }
  729. # endif
  730. template<typename Functor>
  731. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  732. operator==(const function_base& f, reference_wrapper<Functor> g)
  733. {
  734. if (const Functor* fp = f.template target<Functor>())
  735. return fp == g.get_pointer();
  736. else return false;
  737. }
  738. template<typename Functor>
  739. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  740. operator==(reference_wrapper<Functor> g, const function_base& f)
  741. {
  742. if (const Functor* fp = f.template target<Functor>())
  743. return g.get_pointer() == fp;
  744. else return false;
  745. }
  746. template<typename Functor>
  747. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  748. operator!=(const function_base& f, reference_wrapper<Functor> g)
  749. {
  750. if (const Functor* fp = f.template target<Functor>())
  751. return fp != g.get_pointer();
  752. else return true;
  753. }
  754. template<typename Functor>
  755. BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
  756. operator!=(reference_wrapper<Functor> g, const function_base& f)
  757. {
  758. if (const Functor* fp = f.template target<Functor>())
  759. return g.get_pointer() != fp;
  760. else return true;
  761. }
  762. #endif // Compiler supporting SFINAE
  763. namespace detail {
  764. namespace function {
  765. inline bool has_empty_target(const function_base* f)
  766. {
  767. return f->empty();
  768. }
  769. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
  770. inline bool has_empty_target(const void*)
  771. {
  772. return false;
  773. }
  774. #else
  775. inline bool has_empty_target(...)
  776. {
  777. return false;
  778. }
  779. #endif
  780. } // end namespace function
  781. } // end namespace detail
  782. } // end namespace boost
  783. #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
  784. #if defined(BOOST_MSVC)
  785. # pragma warning( pop )
  786. #endif
  787. #endif // BOOST_FUNCTION_BASE_HEADER