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