function_base.hpp 25 KB

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