function_base.hpp 32 KB

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