function_base.hpp 31 KB

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