annotate DEPENDENCIES/generic/include/boost/function/function_base.hpp @ 125:34e428693f5d vext

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