epoc32/include/stdapis/boost/function/function_base.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
williamr@2
     1
// Boost.Function library
williamr@2
     2
williamr@2
     3
//  Copyright Douglas Gregor 2001-2006. Use, modification and
williamr@2
     4
//  distribution is subject to the Boost Software License, Version
williamr@2
     5
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
williamr@2
     6
//  http://www.boost.org/LICENSE_1_0.txt)
williamr@2
     7
williamr@2
     8
// For more information, see http://www.boost.org
williamr@2
     9
williamr@2
    10
#ifndef BOOST_FUNCTION_BASE_HEADER
williamr@2
    11
#define BOOST_FUNCTION_BASE_HEADER
williamr@2
    12
williamr@2
    13
#include <stdexcept>
williamr@2
    14
#include <string>
williamr@2
    15
#include <memory>
williamr@2
    16
#include <new>
williamr@2
    17
#include <typeinfo>
williamr@2
    18
#include <boost/config.hpp>
williamr@2
    19
#include <boost/assert.hpp>
williamr@2
    20
#include <boost/type_traits/is_integral.hpp>
williamr@2
    21
#include <boost/type_traits/composite_traits.hpp>
williamr@2
    22
#include <boost/ref.hpp>
williamr@2
    23
#include <boost/mpl/if.hpp>
williamr@2
    24
#include <boost/detail/workaround.hpp>
williamr@2
    25
#include <boost/type_traits/alignment_of.hpp>
williamr@2
    26
#ifndef BOOST_NO_SFINAE
williamr@2
    27
#  include "boost/utility/enable_if.hpp"
williamr@2
    28
#else
williamr@2
    29
#  include "boost/mpl/bool.hpp"
williamr@2
    30
#endif
williamr@2
    31
#include <boost/function_equal.hpp>
williamr@2
    32
williamr@2
    33
// Borrowed from Boost.Python library: determines the cases where we
williamr@2
    34
// need to use std::type_info::name to compare instead of operator==.
williamr@2
    35
# if (defined(__GNUC__) && __GNUC__ >= 3) \
williamr@2
    36
 || defined(_AIX) \
williamr@2
    37
 || (   defined(__sgi) && defined(__host_mips))
williamr@2
    38
#  include <cstring>
williamr@2
    39
#  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
williamr@2
    40
     (std::strcmp((X).name(),(Y).name()) == 0)
williamr@2
    41
# else
williamr@2
    42
#  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
williamr@2
    43
#endif
williamr@2
    44
williamr@2
    45
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
williamr@2
    46
#  define BOOST_FUNCTION_TARGET_FIX(x) x
williamr@2
    47
#else
williamr@2
    48
#  define BOOST_FUNCTION_TARGET_FIX(x)
williamr@2
    49
#endif // not MSVC
williamr@2
    50
williamr@2
    51
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
williamr@2
    52
// Work around a compiler bug.
williamr@2
    53
// boost::python::objects::function has to be seen by the compiler before the
williamr@2
    54
// boost::function class template.
williamr@2
    55
namespace boost { namespace python { namespace objects {
williamr@2
    56
  class function;
williamr@2
    57
}}}
williamr@2
    58
#endif
williamr@2
    59
williamr@2
    60
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)                    \
williamr@2
    61
 || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG)                         \
williamr@2
    62
 || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
williamr@2
    63
#  define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
williamr@2
    64
#endif
williamr@2
    65
williamr@2
    66
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600)
williamr@2
    67
#  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)              \
williamr@2
    68
      typename ::boost::enable_if_c<(::boost::type_traits::ice_not<          \
williamr@2
    69
                            (::boost::is_integral<Functor>::value)>::value), \
williamr@2
    70
                           Type>::type
williamr@2
    71
#else
williamr@2
    72
// BCC doesn't recognize this depends on a template argument and complains
williamr@2
    73
// about the use of 'typename'
williamr@2
    74
#  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)     \
williamr@2
    75
      ::boost::enable_if_c<(::boost::type_traits::ice_not<          \
williamr@2
    76
                   (::boost::is_integral<Functor>::value)>::value), \
williamr@2
    77
                       Type>::type
williamr@2
    78
#endif
williamr@2
    79
williamr@2
    80
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
williamr@2
    81
namespace boost {
williamr@2
    82
williamr@2
    83
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
williamr@2
    84
// The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
williamr@2
    85
class function_base;
williamr@2
    86
williamr@2
    87
template<typename Signature,
williamr@2
    88
         typename Allocator = std::allocator<function_base> >
williamr@2
    89
class function;
williamr@2
    90
#else
williamr@2
    91
template<typename Signature, typename Allocator = std::allocator<void> >
williamr@2
    92
class function;
williamr@2
    93
#endif
williamr@2
    94
williamr@2
    95
template<typename Signature, typename Allocator>
williamr@2
    96
inline void swap(function<Signature, Allocator>& f1,
williamr@2
    97
                 function<Signature, Allocator>& f2)
williamr@2
    98
{
williamr@2
    99
  f1.swap(f2);
williamr@2
   100
}
williamr@2
   101
williamr@2
   102
} // end namespace boost
williamr@2
   103
#endif // have partial specialization
williamr@2
   104
williamr@2
   105
namespace boost {
williamr@2
   106
  namespace detail {
williamr@2
   107
    namespace function {
williamr@2
   108
      class X;
williamr@2
   109
williamr@2
   110
      /**
williamr@2
   111
       * A buffer used to store small function objects in
williamr@2
   112
       * boost::function. It is a union containing function pointers,
williamr@2
   113
       * object pointers, and a structure that resembles a bound
williamr@2
   114
       * member function pointer.
williamr@2
   115
       */
williamr@2
   116
      union function_buffer
williamr@2
   117
      {
williamr@2
   118
        // For pointers to function objects
williamr@2
   119
        void* obj_ptr;
williamr@2
   120
williamr@2
   121
        // For pointers to std::type_info objects
williamr@2
   122
        // (get_functor_type_tag, check_functor_type_tag).
williamr@2
   123
        const void* const_obj_ptr;
williamr@2
   124
williamr@2
   125
        // For function pointers of all kinds
williamr@2
   126
        mutable void (*func_ptr)();
williamr@2
   127
williamr@2
   128
        // For bound member pointers
williamr@2
   129
        struct bound_memfunc_ptr_t {
williamr@2
   130
          void (X::*memfunc_ptr)(int);
williamr@2
   131
          void* obj_ptr;
williamr@2
   132
        } bound_memfunc_ptr;
williamr@2
   133
williamr@2
   134
        // To relax aliasing constraints
williamr@2
   135
        mutable char data;
williamr@2
   136
      };
williamr@2
   137
williamr@2
   138
      /**
williamr@2
   139
       * The unusable class is a placeholder for unused function arguments
williamr@2
   140
       * It is also completely unusable except that it constructable from
williamr@2
   141
       * anything. This helps compilers without partial specialization to
williamr@2
   142
       * handle Boost.Function objects returning void.
williamr@2
   143
       */
williamr@2
   144
      struct unusable
williamr@2
   145
      {
williamr@2
   146
        unusable() {}
williamr@2
   147
        template<typename T> unusable(const T&) {}
williamr@2
   148
      };
williamr@2
   149
williamr@2
   150
      /* Determine the return type. This supports compilers that do not support
williamr@2
   151
       * void returns or partial specialization by silently changing the return
williamr@2
   152
       * type to "unusable".
williamr@2
   153
       */
williamr@2
   154
      template<typename T> struct function_return_type { typedef T type; };
williamr@2
   155
williamr@2
   156
      template<>
williamr@2
   157
      struct function_return_type<void>
williamr@2
   158
      {
williamr@2
   159
        typedef unusable type;
williamr@2
   160
      };
williamr@2
   161
williamr@2
   162
      // The operation type to perform on the given functor/function pointer
williamr@2
   163
      enum functor_manager_operation_type {
williamr@2
   164
        clone_functor_tag,
williamr@2
   165
        destroy_functor_tag,
williamr@2
   166
        check_functor_type_tag,
williamr@2
   167
        get_functor_type_tag
williamr@2
   168
      };
williamr@2
   169
williamr@2
   170
      // Tags used to decide between different types of functions
williamr@2
   171
      struct function_ptr_tag {};
williamr@2
   172
      struct function_obj_tag {};
williamr@2
   173
      struct member_ptr_tag {};
williamr@2
   174
      struct function_obj_ref_tag {};
williamr@2
   175
williamr@2
   176
      template<typename F>
williamr@2
   177
      class get_function_tag
williamr@2
   178
      {
williamr@2
   179
        typedef typename mpl::if_c<(is_pointer<F>::value),
williamr@2
   180
                                   function_ptr_tag,
williamr@2
   181
                                   function_obj_tag>::type ptr_or_obj_tag;
williamr@2
   182
williamr@2
   183
        typedef typename mpl::if_c<(is_member_pointer<F>::value),
williamr@2
   184
                                   member_ptr_tag,
williamr@2
   185
                                   ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
williamr@2
   186
williamr@2
   187
        typedef typename mpl::if_c<(is_reference_wrapper<F>::value),
williamr@2
   188
                                   function_obj_ref_tag,
williamr@2
   189
                                   ptr_or_obj_or_mem_tag>::type or_ref_tag;
williamr@2
   190
williamr@2
   191
      public:
williamr@2
   192
        typedef or_ref_tag type;
williamr@2
   193
      };
williamr@2
   194
williamr@2
   195
      // The trivial manager does nothing but return the same pointer (if we
williamr@2
   196
      // are cloning) or return the null pointer (if we are deleting).
williamr@2
   197
      template<typename F>
williamr@2
   198
      struct reference_manager
williamr@2
   199
      {
williamr@2
   200
        static inline void
williamr@2
   201
        get(const function_buffer& in_buffer, function_buffer& out_buffer, 
williamr@2
   202
            functor_manager_operation_type op)
williamr@2
   203
        {
williamr@2
   204
          switch (op) {
williamr@2
   205
          case clone_functor_tag: 
williamr@2
   206
            out_buffer.obj_ptr = in_buffer.obj_ptr;
williamr@2
   207
            return;
williamr@2
   208
williamr@2
   209
          case destroy_functor_tag:
williamr@2
   210
            out_buffer.obj_ptr = 0;
williamr@2
   211
            return;
williamr@2
   212
williamr@2
   213
          case check_functor_type_tag:
williamr@2
   214
            {
williamr@2
   215
              // DPG TBD: Since we're only storing a pointer, it's
williamr@2
   216
              // possible that the user could ask for a base class or
williamr@2
   217
              // derived class. Is that okay?
williamr@2
   218
              const std::type_info& check_type = 
williamr@2
   219
                *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
williamr@2
   220
              if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
williamr@2
   221
                out_buffer.obj_ptr = in_buffer.obj_ptr;
williamr@2
   222
              else
williamr@2
   223
                out_buffer.obj_ptr = 0;
williamr@2
   224
            }
williamr@2
   225
            return;
williamr@2
   226
williamr@2
   227
          case get_functor_type_tag:
williamr@2
   228
            out_buffer.const_obj_ptr = &typeid(F);
williamr@2
   229
            return;
williamr@2
   230
          }
williamr@2
   231
        }
williamr@2
   232
      };
williamr@2
   233
williamr@2
   234
      /**
williamr@2
   235
       * Determine if boost::function can use the small-object
williamr@2
   236
       * optimization with the function object type F.
williamr@2
   237
       */
williamr@2
   238
      template<typename F>
williamr@2
   239
      struct function_allows_small_object_optimization
williamr@2
   240
      {
williamr@2
   241
        BOOST_STATIC_CONSTANT
williamr@2
   242
          (bool, 
williamr@2
   243
           value = ((sizeof(F) <= sizeof(function_buffer) &&
williamr@2
   244
                     (alignment_of<function_buffer>::value 
williamr@2
   245
                      % alignment_of<F>::value == 0))));
williamr@2
   246
      };
williamr@2
   247
williamr@2
   248
      /**
williamr@2
   249
       * The functor_manager class contains a static function "manage" which
williamr@2
   250
       * can clone or destroy the given function/function object pointer.
williamr@2
   251
       */
williamr@2
   252
      template<typename Functor, typename Allocator>
williamr@2
   253
      struct functor_manager
williamr@2
   254
      {
williamr@2
   255
      private:
williamr@2
   256
        typedef Functor functor_type;
williamr@2
   257
williamr@2
   258
        // For function pointers, the manager is trivial
williamr@2
   259
        static inline void
williamr@2
   260
        manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
williamr@2
   261
                functor_manager_operation_type op, function_ptr_tag)
williamr@2
   262
        {
williamr@2
   263
          if (op == clone_functor_tag)
williamr@2
   264
            out_buffer.func_ptr = in_buffer.func_ptr;
williamr@2
   265
          else if (op == destroy_functor_tag)
williamr@2
   266
            out_buffer.func_ptr = 0;
williamr@2
   267
          else /* op == check_functor_type_tag */ {
williamr@2
   268
            const std::type_info& check_type = 
williamr@2
   269
              *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
williamr@2
   270
            if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
williamr@2
   271
              out_buffer.obj_ptr = &in_buffer.func_ptr;
williamr@2
   272
            else
williamr@2
   273
              out_buffer.obj_ptr = 0;
williamr@2
   274
          }
williamr@2
   275
        }
williamr@2
   276
williamr@2
   277
        // Function objects that fit in the small-object buffer.
williamr@2
   278
        static inline void
williamr@2
   279
        manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
williamr@2
   280
                functor_manager_operation_type op, mpl::true_)
williamr@2
   281
        {
williamr@2
   282
          if (op == clone_functor_tag) {
williamr@2
   283
            const functor_type* in_functor = 
williamr@2
   284
              reinterpret_cast<const functor_type*>(&in_buffer.data);
williamr@2
   285
            new ((void*)&out_buffer.data) functor_type(*in_functor);
williamr@2
   286
          } else if (op == destroy_functor_tag) {
williamr@2
   287
            // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
williamr@2
   288
            reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
williamr@2
   289
          } else /* op == check_functor_type_tag */ {
williamr@2
   290
            const std::type_info& check_type = 
williamr@2
   291
              *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
williamr@2
   292
            if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
williamr@2
   293
              out_buffer.obj_ptr = &in_buffer.data;
williamr@2
   294
            else
williamr@2
   295
              out_buffer.obj_ptr = 0;
williamr@2
   296
          }
williamr@2
   297
        }
williamr@2
   298
        
williamr@2
   299
        // Function objects that require heap allocation
williamr@2
   300
        static inline void
williamr@2
   301
        manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
williamr@2
   302
                functor_manager_operation_type op, mpl::false_)
williamr@2
   303
        {
williamr@2
   304
#ifndef BOOST_NO_STD_ALLOCATOR
williamr@2
   305
          typedef typename Allocator::template rebind<functor_type>::other
williamr@2
   306
            allocator_type;
williamr@2
   307
          typedef typename allocator_type::pointer pointer_type;
williamr@2
   308
#else
williamr@2
   309
          typedef functor_type* pointer_type;
williamr@2
   310
#endif // BOOST_NO_STD_ALLOCATOR
williamr@2
   311
williamr@2
   312
#  ifndef BOOST_NO_STD_ALLOCATOR
williamr@2
   313
          allocator_type allocator;
williamr@2
   314
#  endif // BOOST_NO_STD_ALLOCATOR
williamr@2
   315
williamr@2
   316
          if (op == clone_functor_tag) {
williamr@2
   317
            // GCC 2.95.3 gets the CV qualifiers wrong here, so we
williamr@2
   318
            // can't do the static_cast that we should do.
williamr@2
   319
            const functor_type* f =
williamr@2
   320
              (const functor_type*)(in_buffer.obj_ptr);
williamr@2
   321
williamr@2
   322
            // Clone the functor
williamr@2
   323
#  ifndef BOOST_NO_STD_ALLOCATOR
williamr@2
   324
            pointer_type copy = allocator.allocate(1);
williamr@2
   325
            allocator.construct(copy, *f);
williamr@2
   326
williamr@2
   327
            // Get back to the original pointer type
williamr@2
   328
            functor_type* new_f = static_cast<functor_type*>(copy);
williamr@2
   329
#  else
williamr@2
   330
            functor_type* new_f = new functor_type(*f);
williamr@2
   331
#  endif // BOOST_NO_STD_ALLOCATOR
williamr@2
   332
            out_buffer.obj_ptr = new_f;
williamr@2
   333
          } else if (op == destroy_functor_tag) {
williamr@2
   334
            /* Cast from the void pointer to the functor pointer type */
williamr@2
   335
            functor_type* f =
williamr@2
   336
              static_cast<functor_type*>(out_buffer.obj_ptr);
williamr@2
   337
williamr@2
   338
#  ifndef BOOST_NO_STD_ALLOCATOR
williamr@2
   339
            /* Cast from the functor pointer type to the allocator's pointer
williamr@2
   340
               type */
williamr@2
   341
            pointer_type victim = static_cast<pointer_type>(f);
williamr@2
   342
williamr@2
   343
            // Destroy and deallocate the functor
williamr@2
   344
            allocator.destroy(victim);
williamr@2
   345
            allocator.deallocate(victim, 1);
williamr@2
   346
#  else
williamr@2
   347
            delete f;
williamr@2
   348
#  endif // BOOST_NO_STD_ALLOCATOR
williamr@2
   349
            out_buffer.obj_ptr = 0;
williamr@2
   350
          } else /* op == check_functor_type_tag */ {
williamr@2
   351
            const std::type_info& check_type = 
williamr@2
   352
              *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
williamr@2
   353
            if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
williamr@2
   354
              out_buffer.obj_ptr = in_buffer.obj_ptr;
williamr@2
   355
            else
williamr@2
   356
              out_buffer.obj_ptr = 0;
williamr@2
   357
          }
williamr@2
   358
        }
williamr@2
   359
williamr@2
   360
        // For function objects, we determine whether the function
williamr@2
   361
        // object can use the small-object optimization buffer or
williamr@2
   362
        // whether we need to allocate it on the heap.
williamr@2
   363
        static inline void
williamr@2
   364
        manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
williamr@2
   365
                functor_manager_operation_type op, function_obj_tag)
williamr@2
   366
        {
williamr@2
   367
          manager(in_buffer, out_buffer, op,
williamr@2
   368
                  mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
williamr@2
   369
        }
williamr@2
   370
williamr@2
   371
      public:
williamr@2
   372
        /* Dispatch to an appropriate manager based on whether we have a
williamr@2
   373
           function pointer or a function object pointer. */
williamr@2
   374
        static inline void
williamr@2
   375
        manage(const function_buffer& in_buffer, function_buffer& out_buffer, 
williamr@2
   376
               functor_manager_operation_type op)
williamr@2
   377
        {
williamr@2
   378
          typedef typename get_function_tag<functor_type>::type tag_type;
williamr@2
   379
          switch (op) {
williamr@2
   380
          case get_functor_type_tag:
williamr@2
   381
            out_buffer.const_obj_ptr = &typeid(functor_type);
williamr@2
   382
            return;
williamr@2
   383
williamr@2
   384
          default:
williamr@2
   385
            manager(in_buffer, out_buffer, op, tag_type());
williamr@2
   386
            return;
williamr@2
   387
          }
williamr@2
   388
        }
williamr@2
   389
      };
williamr@2
   390
williamr@2
   391
      // A type that is only used for comparisons against zero
williamr@2
   392
      struct useless_clear_type {};
williamr@2
   393
williamr@2
   394
#ifdef BOOST_NO_SFINAE
williamr@2
   395
      // These routines perform comparisons between a Boost.Function
williamr@2
   396
      // object and an arbitrary function object (when the last
williamr@2
   397
      // parameter is mpl::bool_<false>) or against zero (when the
williamr@2
   398
      // last parameter is mpl::bool_<true>). They are only necessary
williamr@2
   399
      // for compilers that don't support SFINAE.
williamr@2
   400
      template<typename Function, typename Functor>
williamr@2
   401
        bool
williamr@2
   402
        compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
williamr@2
   403
        { return f.empty(); }
williamr@2
   404
williamr@2
   405
      template<typename Function, typename Functor>
williamr@2
   406
        bool
williamr@2
   407
        compare_not_equal(const Function& f, const Functor&, int,
williamr@2
   408
                          mpl::bool_<true>)
williamr@2
   409
        { return !f.empty(); }
williamr@2
   410
williamr@2
   411
      template<typename Function, typename Functor>
williamr@2
   412
        bool
williamr@2
   413
        compare_equal(const Function& f, const Functor& g, long,
williamr@2
   414
                      mpl::bool_<false>)
williamr@2
   415
        {
williamr@2
   416
          if (const Functor* fp = f.template target<Functor>())
williamr@2
   417
            return function_equal(*fp, g);
williamr@2
   418
          else return false;
williamr@2
   419
        }
williamr@2
   420
williamr@2
   421
      template<typename Function, typename Functor>
williamr@2
   422
        bool
williamr@2
   423
        compare_equal(const Function& f, const reference_wrapper<Functor>& g,
williamr@2
   424
                      int, mpl::bool_<false>)
williamr@2
   425
        {
williamr@2
   426
          if (const Functor* fp = f.template target<Functor>())
williamr@2
   427
            return fp == g.get_pointer();
williamr@2
   428
          else return false;
williamr@2
   429
        }
williamr@2
   430
williamr@2
   431
      template<typename Function, typename Functor>
williamr@2
   432
        bool
williamr@2
   433
        compare_not_equal(const Function& f, const Functor& g, long,
williamr@2
   434
                          mpl::bool_<false>)
williamr@2
   435
        {
williamr@2
   436
          if (const Functor* fp = f.template target<Functor>())
williamr@2
   437
            return !function_equal(*fp, g);
williamr@2
   438
          else return true;
williamr@2
   439
        }
williamr@2
   440
williamr@2
   441
      template<typename Function, typename Functor>
williamr@2
   442
        bool
williamr@2
   443
        compare_not_equal(const Function& f,
williamr@2
   444
                          const reference_wrapper<Functor>& g, int,
williamr@2
   445
                          mpl::bool_<false>)
williamr@2
   446
        {
williamr@2
   447
          if (const Functor* fp = f.template target<Functor>())
williamr@2
   448
            return fp != g.get_pointer();
williamr@2
   449
          else return true;
williamr@2
   450
        }
williamr@2
   451
#endif // BOOST_NO_SFINAE
williamr@2
   452
williamr@2
   453
      /**
williamr@2
   454
       * Stores the "manager" portion of the vtable for a
williamr@2
   455
       * boost::function object.
williamr@2
   456
       */
williamr@2
   457
      struct vtable_base
williamr@2
   458
      {
williamr@2
   459
        vtable_base() : manager(0) { }
williamr@2
   460
        void (*manager)(const function_buffer& in_buffer, 
williamr@2
   461
                        function_buffer& out_buffer, 
williamr@2
   462
                        functor_manager_operation_type op);
williamr@2
   463
      };
williamr@2
   464
    } // end namespace function
williamr@2
   465
  } // end namespace detail
williamr@2
   466
williamr@2
   467
/**
williamr@2
   468
 * The function_base class contains the basic elements needed for the
williamr@2
   469
 * function1, function2, function3, etc. classes. It is common to all
williamr@2
   470
 * functions (and as such can be used to tell if we have one of the
williamr@2
   471
 * functionN objects).
williamr@2
   472
 */
williamr@2
   473
class function_base
williamr@2
   474
{
williamr@2
   475
public:
williamr@2
   476
  function_base() : vtable(0) { }
williamr@2
   477
williamr@2
   478
  /** Determine if the function is empty (i.e., has no target). */
williamr@2
   479
  bool empty() const { return !vtable; }
williamr@2
   480
williamr@2
   481
  /** Retrieve the type of the stored function object, or typeid(void)
williamr@2
   482
      if this is empty. */
williamr@2
   483
  const std::type_info& target_type() const
williamr@2
   484
  {
williamr@2
   485
    if (!vtable) return typeid(void);
williamr@2
   486
williamr@2
   487
    detail::function::function_buffer type;
williamr@2
   488
    vtable->manager(functor, type, detail::function::get_functor_type_tag);
williamr@2
   489
    return *static_cast<const std::type_info*>(type.const_obj_ptr);
williamr@2
   490
  }
williamr@2
   491
williamr@2
   492
  template<typename Functor>
williamr@2
   493
    Functor* target()
williamr@2
   494
    {
williamr@2
   495
      if (!vtable) return 0;
williamr@2
   496
williamr@2
   497
      detail::function::function_buffer type_result;
williamr@2
   498
      type_result.const_obj_ptr = &typeid(Functor);
williamr@2
   499
      vtable->manager(functor, type_result, 
williamr@2
   500
                      detail::function::check_functor_type_tag);
williamr@2
   501
      return static_cast<Functor*>(type_result.obj_ptr);
williamr@2
   502
    }
williamr@2
   503
williamr@2
   504
  template<typename Functor>
williamr@2
   505
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
williamr@2
   506
    const Functor* target( Functor * = 0 ) const
williamr@2
   507
#else
williamr@2
   508
    const Functor* target() const
williamr@2
   509
#endif
williamr@2
   510
    {
williamr@2
   511
      if (!vtable) return 0;
williamr@2
   512
williamr@2
   513
      detail::function::function_buffer type_result;
williamr@2
   514
      type_result.const_obj_ptr = &typeid(Functor);
williamr@2
   515
      vtable->manager(functor, type_result, 
williamr@2
   516
                      detail::function::check_functor_type_tag);
williamr@2
   517
      // GCC 2.95.3 gets the CV qualifiers wrong here, so we
williamr@2
   518
      // can't do the static_cast that we should do.
williamr@2
   519
      return (const Functor*)(type_result.obj_ptr);
williamr@2
   520
    }
williamr@2
   521
williamr@2
   522
  template<typename F>
williamr@2
   523
    bool contains(const F& f) const
williamr@2
   524
    {
williamr@2
   525
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
williamr@2
   526
      if (const F* fp = this->target( (F*)0 ))
williamr@2
   527
#else
williamr@2
   528
      if (const F* fp = this->template target<F>())
williamr@2
   529
#endif
williamr@2
   530
      {
williamr@2
   531
        return function_equal(*fp, f);
williamr@2
   532
      } else {
williamr@2
   533
        return false;
williamr@2
   534
      }
williamr@2
   535
    }
williamr@2
   536
williamr@2
   537
#if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
williamr@2
   538
  // GCC 3.3 and newer cannot copy with the global operator==, due to
williamr@2
   539
  // problems with instantiation of function return types before it
williamr@2
   540
  // has been verified that the argument types match up.
williamr@2
   541
  template<typename Functor>
williamr@2
   542
    BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
williamr@2
   543
    operator==(Functor g) const
williamr@2
   544
    {
williamr@2
   545
      if (const Functor* fp = target<Functor>())
williamr@2
   546
        return function_equal(*fp, g);
williamr@2
   547
      else return false;
williamr@2
   548
    }
williamr@2
   549
williamr@2
   550
  template<typename Functor>
williamr@2
   551
    BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
williamr@2
   552
    operator!=(Functor g) const
williamr@2
   553
    {
williamr@2
   554
      if (const Functor* fp = target<Functor>())
williamr@2
   555
        return !function_equal(*fp, g);
williamr@2
   556
      else return true;
williamr@2
   557
    }
williamr@2
   558
#endif
williamr@2
   559
williamr@2
   560
public: // should be protected, but GCC 2.95.3 will fail to allow access
williamr@2
   561
  detail::function::vtable_base* vtable;
williamr@2
   562
  mutable detail::function::function_buffer functor;
williamr@2
   563
};
williamr@2
   564
williamr@2
   565
/**
williamr@2
   566
 * The bad_function_call exception class is thrown when a boost::function
williamr@2
   567
 * object is invoked
williamr@2
   568
 */
williamr@2
   569
class bad_function_call : public std::runtime_error
williamr@2
   570
{
williamr@2
   571
public:
williamr@2
   572
  bad_function_call() : std::runtime_error("call to empty boost::function") {}
williamr@2
   573
};
williamr@2
   574
williamr@2
   575
#ifndef BOOST_NO_SFINAE
williamr@2
   576
inline bool operator==(const function_base& f,
williamr@2
   577
                       detail::function::useless_clear_type*)
williamr@2
   578
{
williamr@2
   579
  return f.empty();
williamr@2
   580
}
williamr@2
   581
williamr@2
   582
inline bool operator!=(const function_base& f,
williamr@2
   583
                       detail::function::useless_clear_type*)
williamr@2
   584
{
williamr@2
   585
  return !f.empty();
williamr@2
   586
}
williamr@2
   587
williamr@2
   588
inline bool operator==(detail::function::useless_clear_type*,
williamr@2
   589
                       const function_base& f)
williamr@2
   590
{
williamr@2
   591
  return f.empty();
williamr@2
   592
}
williamr@2
   593
williamr@2
   594
inline bool operator!=(detail::function::useless_clear_type*,
williamr@2
   595
                       const function_base& f)
williamr@2
   596
{
williamr@2
   597
  return !f.empty();
williamr@2
   598
}
williamr@2
   599
#endif
williamr@2
   600
williamr@2
   601
#ifdef BOOST_NO_SFINAE
williamr@2
   602
// Comparisons between boost::function objects and arbitrary function objects
williamr@2
   603
template<typename Functor>
williamr@2
   604
  inline bool operator==(const function_base& f, Functor g)
williamr@2
   605
  {
williamr@2
   606
    typedef mpl::bool_<(is_integral<Functor>::value)> integral;
williamr@2
   607
    return detail::function::compare_equal(f, g, 0, integral());
williamr@2
   608
  }
williamr@2
   609
williamr@2
   610
template<typename Functor>
williamr@2
   611
  inline bool operator==(Functor g, const function_base& f)
williamr@2
   612
  {
williamr@2
   613
    typedef mpl::bool_<(is_integral<Functor>::value)> integral;
williamr@2
   614
    return detail::function::compare_equal(f, g, 0, integral());
williamr@2
   615
  }
williamr@2
   616
williamr@2
   617
template<typename Functor>
williamr@2
   618
  inline bool operator!=(const function_base& f, Functor g)
williamr@2
   619
  {
williamr@2
   620
    typedef mpl::bool_<(is_integral<Functor>::value)> integral;
williamr@2
   621
    return detail::function::compare_not_equal(f, g, 0, integral());
williamr@2
   622
  }
williamr@2
   623
williamr@2
   624
template<typename Functor>
williamr@2
   625
  inline bool operator!=(Functor g, const function_base& f)
williamr@2
   626
  {
williamr@2
   627
    typedef mpl::bool_<(is_integral<Functor>::value)> integral;
williamr@2
   628
    return detail::function::compare_not_equal(f, g, 0, integral());
williamr@2
   629
  }
williamr@2
   630
#else
williamr@2
   631
williamr@2
   632
#  if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
williamr@2
   633
// Comparisons between boost::function objects and arbitrary function
williamr@2
   634
// objects. GCC 3.3 and before has an obnoxious bug that prevents this
williamr@2
   635
// from working.
williamr@2
   636
template<typename Functor>
williamr@2
   637
  BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
williamr@2
   638
  operator==(const function_base& f, Functor g)
williamr@2
   639
  {
williamr@2
   640
    if (const Functor* fp = f.template target<Functor>())
williamr@2
   641
      return function_equal(*fp, g);
williamr@2
   642
    else return false;
williamr@2
   643
  }
williamr@2
   644
williamr@2
   645
template<typename Functor>
williamr@2
   646
  BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
williamr@2
   647
  operator==(Functor g, const function_base& f)
williamr@2
   648
  {
williamr@2
   649
    if (const Functor* fp = f.template target<Functor>())
williamr@2
   650
      return function_equal(g, *fp);
williamr@2
   651
    else return false;
williamr@2
   652
  }
williamr@2
   653
williamr@2
   654
template<typename Functor>
williamr@2
   655
  BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
williamr@2
   656
  operator!=(const function_base& f, Functor g)
williamr@2
   657
  {
williamr@2
   658
    if (const Functor* fp = f.template target<Functor>())
williamr@2
   659
      return !function_equal(*fp, g);
williamr@2
   660
    else return true;
williamr@2
   661
  }
williamr@2
   662
williamr@2
   663
template<typename Functor>
williamr@2
   664
  BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
williamr@2
   665
  operator!=(Functor g, const function_base& f)
williamr@2
   666
  {
williamr@2
   667
    if (const Functor* fp = f.template target<Functor>())
williamr@2
   668
      return !function_equal(g, *fp);
williamr@2
   669
    else return true;
williamr@2
   670
  }
williamr@2
   671
#  endif
williamr@2
   672
williamr@2
   673
template<typename Functor>
williamr@2
   674
  BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
williamr@2
   675
  operator==(const function_base& f, reference_wrapper<Functor> g)
williamr@2
   676
  {
williamr@2
   677
    if (const Functor* fp = f.template target<Functor>())
williamr@2
   678
      return fp == g.get_pointer();
williamr@2
   679
    else return false;
williamr@2
   680
  }
williamr@2
   681
williamr@2
   682
template<typename Functor>
williamr@2
   683
  BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
williamr@2
   684
  operator==(reference_wrapper<Functor> g, const function_base& f)
williamr@2
   685
  {
williamr@2
   686
    if (const Functor* fp = f.template target<Functor>())
williamr@2
   687
      return g.get_pointer() == fp;
williamr@2
   688
    else return false;
williamr@2
   689
  }
williamr@2
   690
williamr@2
   691
template<typename Functor>
williamr@2
   692
  BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
williamr@2
   693
  operator!=(const function_base& f, reference_wrapper<Functor> g)
williamr@2
   694
  {
williamr@2
   695
    if (const Functor* fp = f.template target<Functor>())
williamr@2
   696
      return fp != g.get_pointer();
williamr@2
   697
    else return true;
williamr@2
   698
  }
williamr@2
   699
williamr@2
   700
template<typename Functor>
williamr@2
   701
  BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
williamr@2
   702
  operator!=(reference_wrapper<Functor> g, const function_base& f)
williamr@2
   703
  {
williamr@2
   704
    if (const Functor* fp = f.template target<Functor>())
williamr@2
   705
      return g.get_pointer() != fp;
williamr@2
   706
    else return true;
williamr@2
   707
  }
williamr@2
   708
williamr@2
   709
#endif // Compiler supporting SFINAE
williamr@2
   710
williamr@2
   711
namespace detail {
williamr@2
   712
  namespace function {
williamr@2
   713
    inline bool has_empty_target(const function_base* f)
williamr@2
   714
    {
williamr@2
   715
      return f->empty();
williamr@2
   716
    }
williamr@2
   717
williamr@2
   718
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
williamr@2
   719
    inline bool has_empty_target(const void*)
williamr@2
   720
    {
williamr@2
   721
      return false;
williamr@2
   722
    }
williamr@2
   723
#else
williamr@2
   724
    inline bool has_empty_target(...)
williamr@2
   725
    {
williamr@2
   726
      return false;
williamr@2
   727
    }
williamr@2
   728
#endif
williamr@2
   729
  } // end namespace function
williamr@2
   730
} // end namespace detail
williamr@2
   731
} // end namespace boost
williamr@2
   732
williamr@2
   733
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
williamr@2
   734
#undef BOOST_FUNCTION_COMPARE_TYPE_ID
williamr@2
   735
williamr@2
   736
#endif // BOOST_FUNCTION_BASE_HEADER