function_base.hpp 26 KB

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