1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/epoc32/include/stdapis/boost/function/function_base.hpp Tue Mar 16 16:12:26 2010 +0000
1.3 @@ -0,0 +1,736 @@
1.4 +// Boost.Function library
1.5 +
1.6 +// Copyright Douglas Gregor 2001-2006. Use, modification and
1.7 +// distribution is subject to the Boost Software License, Version
1.8 +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
1.9 +// http://www.boost.org/LICENSE_1_0.txt)
1.10 +
1.11 +// For more information, see http://www.boost.org
1.12 +
1.13 +#ifndef BOOST_FUNCTION_BASE_HEADER
1.14 +#define BOOST_FUNCTION_BASE_HEADER
1.15 +
1.16 +#include <stdexcept>
1.17 +#include <string>
1.18 +#include <memory>
1.19 +#include <new>
1.20 +#include <typeinfo>
1.21 +#include <boost/config.hpp>
1.22 +#include <boost/assert.hpp>
1.23 +#include <boost/type_traits/is_integral.hpp>
1.24 +#include <boost/type_traits/composite_traits.hpp>
1.25 +#include <boost/ref.hpp>
1.26 +#include <boost/mpl/if.hpp>
1.27 +#include <boost/detail/workaround.hpp>
1.28 +#include <boost/type_traits/alignment_of.hpp>
1.29 +#ifndef BOOST_NO_SFINAE
1.30 +# include "boost/utility/enable_if.hpp"
1.31 +#else
1.32 +# include "boost/mpl/bool.hpp"
1.33 +#endif
1.34 +#include <boost/function_equal.hpp>
1.35 +
1.36 +// Borrowed from Boost.Python library: determines the cases where we
1.37 +// need to use std::type_info::name to compare instead of operator==.
1.38 +# if (defined(__GNUC__) && __GNUC__ >= 3) \
1.39 + || defined(_AIX) \
1.40 + || ( defined(__sgi) && defined(__host_mips))
1.41 +# include <cstring>
1.42 +# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
1.43 + (std::strcmp((X).name(),(Y).name()) == 0)
1.44 +# else
1.45 +# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
1.46 +#endif
1.47 +
1.48 +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
1.49 +# define BOOST_FUNCTION_TARGET_FIX(x) x
1.50 +#else
1.51 +# define BOOST_FUNCTION_TARGET_FIX(x)
1.52 +#endif // not MSVC
1.53 +
1.54 +#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
1.55 +// Work around a compiler bug.
1.56 +// boost::python::objects::function has to be seen by the compiler before the
1.57 +// boost::function class template.
1.58 +namespace boost { namespace python { namespace objects {
1.59 + class function;
1.60 +}}}
1.61 +#endif
1.62 +
1.63 +#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
1.64 + || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
1.65 + || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
1.66 +# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
1.67 +#endif
1.68 +
1.69 +#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600)
1.70 +# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
1.71 + typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
1.72 + (::boost::is_integral<Functor>::value)>::value), \
1.73 + Type>::type
1.74 +#else
1.75 +// BCC doesn't recognize this depends on a template argument and complains
1.76 +// about the use of 'typename'
1.77 +# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
1.78 + ::boost::enable_if_c<(::boost::type_traits::ice_not< \
1.79 + (::boost::is_integral<Functor>::value)>::value), \
1.80 + Type>::type
1.81 +#endif
1.82 +
1.83 +#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1.84 +namespace boost {
1.85 +
1.86 +#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
1.87 +// The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
1.88 +class function_base;
1.89 +
1.90 +template<typename Signature,
1.91 + typename Allocator = std::allocator<function_base> >
1.92 +class function;
1.93 +#else
1.94 +template<typename Signature, typename Allocator = std::allocator<void> >
1.95 +class function;
1.96 +#endif
1.97 +
1.98 +template<typename Signature, typename Allocator>
1.99 +inline void swap(function<Signature, Allocator>& f1,
1.100 + function<Signature, Allocator>& f2)
1.101 +{
1.102 + f1.swap(f2);
1.103 +}
1.104 +
1.105 +} // end namespace boost
1.106 +#endif // have partial specialization
1.107 +
1.108 +namespace boost {
1.109 + namespace detail {
1.110 + namespace function {
1.111 + class X;
1.112 +
1.113 + /**
1.114 + * A buffer used to store small function objects in
1.115 + * boost::function. It is a union containing function pointers,
1.116 + * object pointers, and a structure that resembles a bound
1.117 + * member function pointer.
1.118 + */
1.119 + union function_buffer
1.120 + {
1.121 + // For pointers to function objects
1.122 + void* obj_ptr;
1.123 +
1.124 + // For pointers to std::type_info objects
1.125 + // (get_functor_type_tag, check_functor_type_tag).
1.126 + const void* const_obj_ptr;
1.127 +
1.128 + // For function pointers of all kinds
1.129 + mutable void (*func_ptr)();
1.130 +
1.131 + // For bound member pointers
1.132 + struct bound_memfunc_ptr_t {
1.133 + void (X::*memfunc_ptr)(int);
1.134 + void* obj_ptr;
1.135 + } bound_memfunc_ptr;
1.136 +
1.137 + // To relax aliasing constraints
1.138 + mutable char data;
1.139 + };
1.140 +
1.141 + /**
1.142 + * The unusable class is a placeholder for unused function arguments
1.143 + * It is also completely unusable except that it constructable from
1.144 + * anything. This helps compilers without partial specialization to
1.145 + * handle Boost.Function objects returning void.
1.146 + */
1.147 + struct unusable
1.148 + {
1.149 + unusable() {}
1.150 + template<typename T> unusable(const T&) {}
1.151 + };
1.152 +
1.153 + /* Determine the return type. This supports compilers that do not support
1.154 + * void returns or partial specialization by silently changing the return
1.155 + * type to "unusable".
1.156 + */
1.157 + template<typename T> struct function_return_type { typedef T type; };
1.158 +
1.159 + template<>
1.160 + struct function_return_type<void>
1.161 + {
1.162 + typedef unusable type;
1.163 + };
1.164 +
1.165 + // The operation type to perform on the given functor/function pointer
1.166 + enum functor_manager_operation_type {
1.167 + clone_functor_tag,
1.168 + destroy_functor_tag,
1.169 + check_functor_type_tag,
1.170 + get_functor_type_tag
1.171 + };
1.172 +
1.173 + // Tags used to decide between different types of functions
1.174 + struct function_ptr_tag {};
1.175 + struct function_obj_tag {};
1.176 + struct member_ptr_tag {};
1.177 + struct function_obj_ref_tag {};
1.178 +
1.179 + template<typename F>
1.180 + class get_function_tag
1.181 + {
1.182 + typedef typename mpl::if_c<(is_pointer<F>::value),
1.183 + function_ptr_tag,
1.184 + function_obj_tag>::type ptr_or_obj_tag;
1.185 +
1.186 + typedef typename mpl::if_c<(is_member_pointer<F>::value),
1.187 + member_ptr_tag,
1.188 + ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
1.189 +
1.190 + typedef typename mpl::if_c<(is_reference_wrapper<F>::value),
1.191 + function_obj_ref_tag,
1.192 + ptr_or_obj_or_mem_tag>::type or_ref_tag;
1.193 +
1.194 + public:
1.195 + typedef or_ref_tag type;
1.196 + };
1.197 +
1.198 + // The trivial manager does nothing but return the same pointer (if we
1.199 + // are cloning) or return the null pointer (if we are deleting).
1.200 + template<typename F>
1.201 + struct reference_manager
1.202 + {
1.203 + static inline void
1.204 + get(const function_buffer& in_buffer, function_buffer& out_buffer,
1.205 + functor_manager_operation_type op)
1.206 + {
1.207 + switch (op) {
1.208 + case clone_functor_tag:
1.209 + out_buffer.obj_ptr = in_buffer.obj_ptr;
1.210 + return;
1.211 +
1.212 + case destroy_functor_tag:
1.213 + out_buffer.obj_ptr = 0;
1.214 + return;
1.215 +
1.216 + case check_functor_type_tag:
1.217 + {
1.218 + // DPG TBD: Since we're only storing a pointer, it's
1.219 + // possible that the user could ask for a base class or
1.220 + // derived class. Is that okay?
1.221 + const std::type_info& check_type =
1.222 + *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
1.223 + if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
1.224 + out_buffer.obj_ptr = in_buffer.obj_ptr;
1.225 + else
1.226 + out_buffer.obj_ptr = 0;
1.227 + }
1.228 + return;
1.229 +
1.230 + case get_functor_type_tag:
1.231 + out_buffer.const_obj_ptr = &typeid(F);
1.232 + return;
1.233 + }
1.234 + }
1.235 + };
1.236 +
1.237 + /**
1.238 + * Determine if boost::function can use the small-object
1.239 + * optimization with the function object type F.
1.240 + */
1.241 + template<typename F>
1.242 + struct function_allows_small_object_optimization
1.243 + {
1.244 + BOOST_STATIC_CONSTANT
1.245 + (bool,
1.246 + value = ((sizeof(F) <= sizeof(function_buffer) &&
1.247 + (alignment_of<function_buffer>::value
1.248 + % alignment_of<F>::value == 0))));
1.249 + };
1.250 +
1.251 + /**
1.252 + * The functor_manager class contains a static function "manage" which
1.253 + * can clone or destroy the given function/function object pointer.
1.254 + */
1.255 + template<typename Functor, typename Allocator>
1.256 + struct functor_manager
1.257 + {
1.258 + private:
1.259 + typedef Functor functor_type;
1.260 +
1.261 + // For function pointers, the manager is trivial
1.262 + static inline void
1.263 + manager(const function_buffer& in_buffer, function_buffer& out_buffer,
1.264 + functor_manager_operation_type op, function_ptr_tag)
1.265 + {
1.266 + if (op == clone_functor_tag)
1.267 + out_buffer.func_ptr = in_buffer.func_ptr;
1.268 + else if (op == destroy_functor_tag)
1.269 + out_buffer.func_ptr = 0;
1.270 + else /* op == check_functor_type_tag */ {
1.271 + const std::type_info& check_type =
1.272 + *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
1.273 + if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
1.274 + out_buffer.obj_ptr = &in_buffer.func_ptr;
1.275 + else
1.276 + out_buffer.obj_ptr = 0;
1.277 + }
1.278 + }
1.279 +
1.280 + // Function objects that fit in the small-object buffer.
1.281 + static inline void
1.282 + manager(const function_buffer& in_buffer, function_buffer& out_buffer,
1.283 + functor_manager_operation_type op, mpl::true_)
1.284 + {
1.285 + if (op == clone_functor_tag) {
1.286 + const functor_type* in_functor =
1.287 + reinterpret_cast<const functor_type*>(&in_buffer.data);
1.288 + new ((void*)&out_buffer.data) functor_type(*in_functor);
1.289 + } else if (op == destroy_functor_tag) {
1.290 + // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
1.291 + reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
1.292 + } else /* op == check_functor_type_tag */ {
1.293 + const std::type_info& check_type =
1.294 + *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
1.295 + if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
1.296 + out_buffer.obj_ptr = &in_buffer.data;
1.297 + else
1.298 + out_buffer.obj_ptr = 0;
1.299 + }
1.300 + }
1.301 +
1.302 + // Function objects that require heap allocation
1.303 + static inline void
1.304 + manager(const function_buffer& in_buffer, function_buffer& out_buffer,
1.305 + functor_manager_operation_type op, mpl::false_)
1.306 + {
1.307 +#ifndef BOOST_NO_STD_ALLOCATOR
1.308 + typedef typename Allocator::template rebind<functor_type>::other
1.309 + allocator_type;
1.310 + typedef typename allocator_type::pointer pointer_type;
1.311 +#else
1.312 + typedef functor_type* pointer_type;
1.313 +#endif // BOOST_NO_STD_ALLOCATOR
1.314 +
1.315 +# ifndef BOOST_NO_STD_ALLOCATOR
1.316 + allocator_type allocator;
1.317 +# endif // BOOST_NO_STD_ALLOCATOR
1.318 +
1.319 + if (op == clone_functor_tag) {
1.320 + // GCC 2.95.3 gets the CV qualifiers wrong here, so we
1.321 + // can't do the static_cast that we should do.
1.322 + const functor_type* f =
1.323 + (const functor_type*)(in_buffer.obj_ptr);
1.324 +
1.325 + // Clone the functor
1.326 +# ifndef BOOST_NO_STD_ALLOCATOR
1.327 + pointer_type copy = allocator.allocate(1);
1.328 + allocator.construct(copy, *f);
1.329 +
1.330 + // Get back to the original pointer type
1.331 + functor_type* new_f = static_cast<functor_type*>(copy);
1.332 +# else
1.333 + functor_type* new_f = new functor_type(*f);
1.334 +# endif // BOOST_NO_STD_ALLOCATOR
1.335 + out_buffer.obj_ptr = new_f;
1.336 + } else if (op == destroy_functor_tag) {
1.337 + /* Cast from the void pointer to the functor pointer type */
1.338 + functor_type* f =
1.339 + static_cast<functor_type*>(out_buffer.obj_ptr);
1.340 +
1.341 +# ifndef BOOST_NO_STD_ALLOCATOR
1.342 + /* Cast from the functor pointer type to the allocator's pointer
1.343 + type */
1.344 + pointer_type victim = static_cast<pointer_type>(f);
1.345 +
1.346 + // Destroy and deallocate the functor
1.347 + allocator.destroy(victim);
1.348 + allocator.deallocate(victim, 1);
1.349 +# else
1.350 + delete f;
1.351 +# endif // BOOST_NO_STD_ALLOCATOR
1.352 + out_buffer.obj_ptr = 0;
1.353 + } else /* op == check_functor_type_tag */ {
1.354 + const std::type_info& check_type =
1.355 + *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
1.356 + if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
1.357 + out_buffer.obj_ptr = in_buffer.obj_ptr;
1.358 + else
1.359 + out_buffer.obj_ptr = 0;
1.360 + }
1.361 + }
1.362 +
1.363 + // For function objects, we determine whether the function
1.364 + // object can use the small-object optimization buffer or
1.365 + // whether we need to allocate it on the heap.
1.366 + static inline void
1.367 + manager(const function_buffer& in_buffer, function_buffer& out_buffer,
1.368 + functor_manager_operation_type op, function_obj_tag)
1.369 + {
1.370 + manager(in_buffer, out_buffer, op,
1.371 + mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
1.372 + }
1.373 +
1.374 + public:
1.375 + /* Dispatch to an appropriate manager based on whether we have a
1.376 + function pointer or a function object pointer. */
1.377 + static inline void
1.378 + manage(const function_buffer& in_buffer, function_buffer& out_buffer,
1.379 + functor_manager_operation_type op)
1.380 + {
1.381 + typedef typename get_function_tag<functor_type>::type tag_type;
1.382 + switch (op) {
1.383 + case get_functor_type_tag:
1.384 + out_buffer.const_obj_ptr = &typeid(functor_type);
1.385 + return;
1.386 +
1.387 + default:
1.388 + manager(in_buffer, out_buffer, op, tag_type());
1.389 + return;
1.390 + }
1.391 + }
1.392 + };
1.393 +
1.394 + // A type that is only used for comparisons against zero
1.395 + struct useless_clear_type {};
1.396 +
1.397 +#ifdef BOOST_NO_SFINAE
1.398 + // These routines perform comparisons between a Boost.Function
1.399 + // object and an arbitrary function object (when the last
1.400 + // parameter is mpl::bool_<false>) or against zero (when the
1.401 + // last parameter is mpl::bool_<true>). They are only necessary
1.402 + // for compilers that don't support SFINAE.
1.403 + template<typename Function, typename Functor>
1.404 + bool
1.405 + compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
1.406 + { return f.empty(); }
1.407 +
1.408 + template<typename Function, typename Functor>
1.409 + bool
1.410 + compare_not_equal(const Function& f, const Functor&, int,
1.411 + mpl::bool_<true>)
1.412 + { return !f.empty(); }
1.413 +
1.414 + template<typename Function, typename Functor>
1.415 + bool
1.416 + compare_equal(const Function& f, const Functor& g, long,
1.417 + mpl::bool_<false>)
1.418 + {
1.419 + if (const Functor* fp = f.template target<Functor>())
1.420 + return function_equal(*fp, g);
1.421 + else return false;
1.422 + }
1.423 +
1.424 + template<typename Function, typename Functor>
1.425 + bool
1.426 + compare_equal(const Function& f, const reference_wrapper<Functor>& g,
1.427 + int, mpl::bool_<false>)
1.428 + {
1.429 + if (const Functor* fp = f.template target<Functor>())
1.430 + return fp == g.get_pointer();
1.431 + else return false;
1.432 + }
1.433 +
1.434 + template<typename Function, typename Functor>
1.435 + bool
1.436 + compare_not_equal(const Function& f, const Functor& g, long,
1.437 + mpl::bool_<false>)
1.438 + {
1.439 + if (const Functor* fp = f.template target<Functor>())
1.440 + return !function_equal(*fp, g);
1.441 + else return true;
1.442 + }
1.443 +
1.444 + template<typename Function, typename Functor>
1.445 + bool
1.446 + compare_not_equal(const Function& f,
1.447 + const reference_wrapper<Functor>& g, int,
1.448 + mpl::bool_<false>)
1.449 + {
1.450 + if (const Functor* fp = f.template target<Functor>())
1.451 + return fp != g.get_pointer();
1.452 + else return true;
1.453 + }
1.454 +#endif // BOOST_NO_SFINAE
1.455 +
1.456 + /**
1.457 + * Stores the "manager" portion of the vtable for a
1.458 + * boost::function object.
1.459 + */
1.460 + struct vtable_base
1.461 + {
1.462 + vtable_base() : manager(0) { }
1.463 + void (*manager)(const function_buffer& in_buffer,
1.464 + function_buffer& out_buffer,
1.465 + functor_manager_operation_type op);
1.466 + };
1.467 + } // end namespace function
1.468 + } // end namespace detail
1.469 +
1.470 +/**
1.471 + * The function_base class contains the basic elements needed for the
1.472 + * function1, function2, function3, etc. classes. It is common to all
1.473 + * functions (and as such can be used to tell if we have one of the
1.474 + * functionN objects).
1.475 + */
1.476 +class function_base
1.477 +{
1.478 +public:
1.479 + function_base() : vtable(0) { }
1.480 +
1.481 + /** Determine if the function is empty (i.e., has no target). */
1.482 + bool empty() const { return !vtable; }
1.483 +
1.484 + /** Retrieve the type of the stored function object, or typeid(void)
1.485 + if this is empty. */
1.486 + const std::type_info& target_type() const
1.487 + {
1.488 + if (!vtable) return typeid(void);
1.489 +
1.490 + detail::function::function_buffer type;
1.491 + vtable->manager(functor, type, detail::function::get_functor_type_tag);
1.492 + return *static_cast<const std::type_info*>(type.const_obj_ptr);
1.493 + }
1.494 +
1.495 + template<typename Functor>
1.496 + Functor* target()
1.497 + {
1.498 + if (!vtable) return 0;
1.499 +
1.500 + detail::function::function_buffer type_result;
1.501 + type_result.const_obj_ptr = &typeid(Functor);
1.502 + vtable->manager(functor, type_result,
1.503 + detail::function::check_functor_type_tag);
1.504 + return static_cast<Functor*>(type_result.obj_ptr);
1.505 + }
1.506 +
1.507 + template<typename Functor>
1.508 +#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
1.509 + const Functor* target( Functor * = 0 ) const
1.510 +#else
1.511 + const Functor* target() const
1.512 +#endif
1.513 + {
1.514 + if (!vtable) return 0;
1.515 +
1.516 + detail::function::function_buffer type_result;
1.517 + type_result.const_obj_ptr = &typeid(Functor);
1.518 + vtable->manager(functor, type_result,
1.519 + detail::function::check_functor_type_tag);
1.520 + // GCC 2.95.3 gets the CV qualifiers wrong here, so we
1.521 + // can't do the static_cast that we should do.
1.522 + return (const Functor*)(type_result.obj_ptr);
1.523 + }
1.524 +
1.525 + template<typename F>
1.526 + bool contains(const F& f) const
1.527 + {
1.528 +#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
1.529 + if (const F* fp = this->target( (F*)0 ))
1.530 +#else
1.531 + if (const F* fp = this->template target<F>())
1.532 +#endif
1.533 + {
1.534 + return function_equal(*fp, f);
1.535 + } else {
1.536 + return false;
1.537 + }
1.538 + }
1.539 +
1.540 +#if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
1.541 + // GCC 3.3 and newer cannot copy with the global operator==, due to
1.542 + // problems with instantiation of function return types before it
1.543 + // has been verified that the argument types match up.
1.544 + template<typename Functor>
1.545 + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
1.546 + operator==(Functor g) const
1.547 + {
1.548 + if (const Functor* fp = target<Functor>())
1.549 + return function_equal(*fp, g);
1.550 + else return false;
1.551 + }
1.552 +
1.553 + template<typename Functor>
1.554 + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
1.555 + operator!=(Functor g) const
1.556 + {
1.557 + if (const Functor* fp = target<Functor>())
1.558 + return !function_equal(*fp, g);
1.559 + else return true;
1.560 + }
1.561 +#endif
1.562 +
1.563 +public: // should be protected, but GCC 2.95.3 will fail to allow access
1.564 + detail::function::vtable_base* vtable;
1.565 + mutable detail::function::function_buffer functor;
1.566 +};
1.567 +
1.568 +/**
1.569 + * The bad_function_call exception class is thrown when a boost::function
1.570 + * object is invoked
1.571 + */
1.572 +class bad_function_call : public std::runtime_error
1.573 +{
1.574 +public:
1.575 + bad_function_call() : std::runtime_error("call to empty boost::function") {}
1.576 +};
1.577 +
1.578 +#ifndef BOOST_NO_SFINAE
1.579 +inline bool operator==(const function_base& f,
1.580 + detail::function::useless_clear_type*)
1.581 +{
1.582 + return f.empty();
1.583 +}
1.584 +
1.585 +inline bool operator!=(const function_base& f,
1.586 + detail::function::useless_clear_type*)
1.587 +{
1.588 + return !f.empty();
1.589 +}
1.590 +
1.591 +inline bool operator==(detail::function::useless_clear_type*,
1.592 + const function_base& f)
1.593 +{
1.594 + return f.empty();
1.595 +}
1.596 +
1.597 +inline bool operator!=(detail::function::useless_clear_type*,
1.598 + const function_base& f)
1.599 +{
1.600 + return !f.empty();
1.601 +}
1.602 +#endif
1.603 +
1.604 +#ifdef BOOST_NO_SFINAE
1.605 +// Comparisons between boost::function objects and arbitrary function objects
1.606 +template<typename Functor>
1.607 + inline bool operator==(const function_base& f, Functor g)
1.608 + {
1.609 + typedef mpl::bool_<(is_integral<Functor>::value)> integral;
1.610 + return detail::function::compare_equal(f, g, 0, integral());
1.611 + }
1.612 +
1.613 +template<typename Functor>
1.614 + inline bool operator==(Functor g, const function_base& f)
1.615 + {
1.616 + typedef mpl::bool_<(is_integral<Functor>::value)> integral;
1.617 + return detail::function::compare_equal(f, g, 0, integral());
1.618 + }
1.619 +
1.620 +template<typename Functor>
1.621 + inline bool operator!=(const function_base& f, Functor g)
1.622 + {
1.623 + typedef mpl::bool_<(is_integral<Functor>::value)> integral;
1.624 + return detail::function::compare_not_equal(f, g, 0, integral());
1.625 + }
1.626 +
1.627 +template<typename Functor>
1.628 + inline bool operator!=(Functor g, const function_base& f)
1.629 + {
1.630 + typedef mpl::bool_<(is_integral<Functor>::value)> integral;
1.631 + return detail::function::compare_not_equal(f, g, 0, integral());
1.632 + }
1.633 +#else
1.634 +
1.635 +# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
1.636 +// Comparisons between boost::function objects and arbitrary function
1.637 +// objects. GCC 3.3 and before has an obnoxious bug that prevents this
1.638 +// from working.
1.639 +template<typename Functor>
1.640 + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
1.641 + operator==(const function_base& f, Functor g)
1.642 + {
1.643 + if (const Functor* fp = f.template target<Functor>())
1.644 + return function_equal(*fp, g);
1.645 + else return false;
1.646 + }
1.647 +
1.648 +template<typename Functor>
1.649 + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
1.650 + operator==(Functor g, const function_base& f)
1.651 + {
1.652 + if (const Functor* fp = f.template target<Functor>())
1.653 + return function_equal(g, *fp);
1.654 + else return false;
1.655 + }
1.656 +
1.657 +template<typename Functor>
1.658 + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
1.659 + operator!=(const function_base& f, Functor g)
1.660 + {
1.661 + if (const Functor* fp = f.template target<Functor>())
1.662 + return !function_equal(*fp, g);
1.663 + else return true;
1.664 + }
1.665 +
1.666 +template<typename Functor>
1.667 + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
1.668 + operator!=(Functor g, const function_base& f)
1.669 + {
1.670 + if (const Functor* fp = f.template target<Functor>())
1.671 + return !function_equal(g, *fp);
1.672 + else return true;
1.673 + }
1.674 +# endif
1.675 +
1.676 +template<typename Functor>
1.677 + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
1.678 + operator==(const function_base& f, reference_wrapper<Functor> g)
1.679 + {
1.680 + if (const Functor* fp = f.template target<Functor>())
1.681 + return fp == g.get_pointer();
1.682 + else return false;
1.683 + }
1.684 +
1.685 +template<typename Functor>
1.686 + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
1.687 + operator==(reference_wrapper<Functor> g, const function_base& f)
1.688 + {
1.689 + if (const Functor* fp = f.template target<Functor>())
1.690 + return g.get_pointer() == fp;
1.691 + else return false;
1.692 + }
1.693 +
1.694 +template<typename Functor>
1.695 + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
1.696 + operator!=(const function_base& f, reference_wrapper<Functor> g)
1.697 + {
1.698 + if (const Functor* fp = f.template target<Functor>())
1.699 + return fp != g.get_pointer();
1.700 + else return true;
1.701 + }
1.702 +
1.703 +template<typename Functor>
1.704 + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
1.705 + operator!=(reference_wrapper<Functor> g, const function_base& f)
1.706 + {
1.707 + if (const Functor* fp = f.template target<Functor>())
1.708 + return g.get_pointer() != fp;
1.709 + else return true;
1.710 + }
1.711 +
1.712 +#endif // Compiler supporting SFINAE
1.713 +
1.714 +namespace detail {
1.715 + namespace function {
1.716 + inline bool has_empty_target(const function_base* f)
1.717 + {
1.718 + return f->empty();
1.719 + }
1.720 +
1.721 +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
1.722 + inline bool has_empty_target(const void*)
1.723 + {
1.724 + return false;
1.725 + }
1.726 +#else
1.727 + inline bool has_empty_target(...)
1.728 + {
1.729 + return false;
1.730 + }
1.731 +#endif
1.732 + } // end namespace function
1.733 +} // end namespace detail
1.734 +} // end namespace boost
1.735 +
1.736 +#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
1.737 +#undef BOOST_FUNCTION_COMPARE_TYPE_ID
1.738 +
1.739 +#endif // BOOST_FUNCTION_BASE_HEADER