function_base.hpp 31 KB

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