function_base.hpp 31 KB

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