os/ossrv/ossrv_pub/boost_apis/boost/function/function_template.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Boost.Function library
sl@0
     2
sl@0
     3
//  Copyright Douglas Gregor 2001-2006. Use, modification and
sl@0
     4
//  distribution is subject to the Boost Software License, Version
sl@0
     5
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
sl@0
     6
//  http://www.boost.org/LICENSE_1_0.txt)
sl@0
     7
sl@0
     8
// For more information, see http://www.boost.org
sl@0
     9
sl@0
    10
// Note: this header is a header template and must NOT have multiple-inclusion
sl@0
    11
// protection.
sl@0
    12
#include <boost/function/detail/prologue.hpp>
sl@0
    13
sl@0
    14
#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
sl@0
    15
sl@0
    16
#define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
sl@0
    17
sl@0
    18
#define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
sl@0
    19
sl@0
    20
#define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
sl@0
    21
sl@0
    22
#define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
sl@0
    23
sl@0
    24
#define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
sl@0
    25
  typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
sl@0
    26
sl@0
    27
#define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
sl@0
    28
sl@0
    29
// Type of the default allocator
sl@0
    30
#ifndef BOOST_NO_STD_ALLOCATOR
sl@0
    31
#  define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
sl@0
    32
#else
sl@0
    33
#  define BOOST_FUNCTION_DEFAULT_ALLOCATOR int
sl@0
    34
#endif // BOOST_NO_STD_ALLOCATOR
sl@0
    35
sl@0
    36
// Comma if nonzero number of arguments
sl@0
    37
#if BOOST_FUNCTION_NUM_ARGS == 0
sl@0
    38
#  define BOOST_FUNCTION_COMMA
sl@0
    39
#else
sl@0
    40
#  define BOOST_FUNCTION_COMMA ,
sl@0
    41
#endif // BOOST_FUNCTION_NUM_ARGS > 0
sl@0
    42
sl@0
    43
// Class names used in this version of the code
sl@0
    44
#define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
sl@0
    45
#define BOOST_FUNCTION_FUNCTION_INVOKER \
sl@0
    46
  BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
sl@0
    47
#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
sl@0
    48
  BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
sl@0
    49
#define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
sl@0
    50
  BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
sl@0
    51
#define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
sl@0
    52
  BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
sl@0
    53
#define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
sl@0
    54
  BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
sl@0
    55
#define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
sl@0
    56
  BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
sl@0
    57
#define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
sl@0
    58
  BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
sl@0
    59
#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
sl@0
    60
  BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
sl@0
    61
#define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
sl@0
    62
  BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
sl@0
    63
#define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
sl@0
    64
sl@0
    65
#ifndef BOOST_NO_VOID_RETURNS
sl@0
    66
#  define BOOST_FUNCTION_VOID_RETURN_TYPE void
sl@0
    67
#  define BOOST_FUNCTION_RETURN(X) X
sl@0
    68
#else
sl@0
    69
#  define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable
sl@0
    70
#  define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
sl@0
    71
#endif
sl@0
    72
sl@0
    73
#ifdef BOOST_MSVC
sl@0
    74
#  pragma warning(push)
sl@0
    75
#  pragma warning(disable: 4127) // conditional expression is constant.
sl@0
    76
#endif
sl@0
    77
sl@0
    78
#ifdef BOOST_MSVC
sl@0
    79
#  pragma warning(push)
sl@0
    80
#  pragma warning(disable: 4127) // conditional expression is constant.
sl@0
    81
#endif
sl@0
    82
sl@0
    83
namespace boost {
sl@0
    84
  namespace detail {
sl@0
    85
    namespace function {
sl@0
    86
      template<
sl@0
    87
        typename FunctionPtr,
sl@0
    88
        typename R BOOST_FUNCTION_COMMA
sl@0
    89
        BOOST_FUNCTION_TEMPLATE_PARMS
sl@0
    90
        >
sl@0
    91
      struct BOOST_FUNCTION_FUNCTION_INVOKER
sl@0
    92
      {
sl@0
    93
        static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
sl@0
    94
                        BOOST_FUNCTION_PARMS)
sl@0
    95
        {
sl@0
    96
          FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
sl@0
    97
          return f(BOOST_FUNCTION_ARGS);
sl@0
    98
        }
sl@0
    99
      };
sl@0
   100
sl@0
   101
      template<
sl@0
   102
        typename FunctionPtr,
sl@0
   103
        typename R BOOST_FUNCTION_COMMA
sl@0
   104
        BOOST_FUNCTION_TEMPLATE_PARMS
sl@0
   105
        >
sl@0
   106
      struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
sl@0
   107
      {
sl@0
   108
        static BOOST_FUNCTION_VOID_RETURN_TYPE
sl@0
   109
        invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
sl@0
   110
               BOOST_FUNCTION_PARMS)
sl@0
   111
sl@0
   112
        {
sl@0
   113
          FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
sl@0
   114
          BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
sl@0
   115
        }
sl@0
   116
      };
sl@0
   117
sl@0
   118
      template<
sl@0
   119
        typename FunctionObj,
sl@0
   120
        typename R BOOST_FUNCTION_COMMA
sl@0
   121
        BOOST_FUNCTION_TEMPLATE_PARMS
sl@0
   122
      >
sl@0
   123
      struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
sl@0
   124
      {
sl@0
   125
        static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
sl@0
   126
                        BOOST_FUNCTION_PARMS)
sl@0
   127
sl@0
   128
        {
sl@0
   129
          FunctionObj* f;
sl@0
   130
          if (function_allows_small_object_optimization<FunctionObj>::value)
sl@0
   131
            f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
sl@0
   132
          else
sl@0
   133
            f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
sl@0
   134
          return (*f)(BOOST_FUNCTION_ARGS);
sl@0
   135
        }
sl@0
   136
      };
sl@0
   137
sl@0
   138
      template<
sl@0
   139
        typename FunctionObj,
sl@0
   140
        typename R BOOST_FUNCTION_COMMA
sl@0
   141
        BOOST_FUNCTION_TEMPLATE_PARMS
sl@0
   142
      >
sl@0
   143
      struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
sl@0
   144
      {
sl@0
   145
        static BOOST_FUNCTION_VOID_RETURN_TYPE
sl@0
   146
        invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
sl@0
   147
               BOOST_FUNCTION_PARMS)
sl@0
   148
sl@0
   149
        {
sl@0
   150
          FunctionObj* f;
sl@0
   151
          if (function_allows_small_object_optimization<FunctionObj>::value)
sl@0
   152
            f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
sl@0
   153
          else
sl@0
   154
            f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
sl@0
   155
          BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
sl@0
   156
        }
sl@0
   157
      };
sl@0
   158
sl@0
   159
      template<
sl@0
   160
        typename FunctionObj,
sl@0
   161
        typename R BOOST_FUNCTION_COMMA
sl@0
   162
        BOOST_FUNCTION_TEMPLATE_PARMS
sl@0
   163
      >
sl@0
   164
      struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
sl@0
   165
      {
sl@0
   166
        static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
sl@0
   167
                        BOOST_FUNCTION_PARMS)
sl@0
   168
sl@0
   169
        {
sl@0
   170
          FunctionObj* f = 
sl@0
   171
            reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
sl@0
   172
          return (*f)(BOOST_FUNCTION_ARGS);
sl@0
   173
        }
sl@0
   174
      };
sl@0
   175
sl@0
   176
      template<
sl@0
   177
        typename FunctionObj,
sl@0
   178
        typename R BOOST_FUNCTION_COMMA
sl@0
   179
        BOOST_FUNCTION_TEMPLATE_PARMS
sl@0
   180
      >
sl@0
   181
      struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
sl@0
   182
      {
sl@0
   183
        static BOOST_FUNCTION_VOID_RETURN_TYPE
sl@0
   184
        invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
sl@0
   185
               BOOST_FUNCTION_PARMS)
sl@0
   186
sl@0
   187
        {
sl@0
   188
          FunctionObj* f = 
sl@0
   189
            reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
sl@0
   190
          BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
sl@0
   191
        }
sl@0
   192
      };
sl@0
   193
sl@0
   194
      template<
sl@0
   195
        typename FunctionPtr,
sl@0
   196
        typename R BOOST_FUNCTION_COMMA
sl@0
   197
        BOOST_FUNCTION_TEMPLATE_PARMS
sl@0
   198
      >
sl@0
   199
      struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
sl@0
   200
      {
sl@0
   201
        typedef typename mpl::if_c<(is_void<R>::value),
sl@0
   202
                            BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
sl@0
   203
                            FunctionPtr,
sl@0
   204
                            R BOOST_FUNCTION_COMMA
sl@0
   205
                            BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   206
                          >,
sl@0
   207
                          BOOST_FUNCTION_FUNCTION_INVOKER<
sl@0
   208
                            FunctionPtr,
sl@0
   209
                            R BOOST_FUNCTION_COMMA
sl@0
   210
                            BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   211
                          >
sl@0
   212
                       >::type type;
sl@0
   213
      };
sl@0
   214
sl@0
   215
      template<
sl@0
   216
        typename FunctionObj,
sl@0
   217
        typename R BOOST_FUNCTION_COMMA
sl@0
   218
        BOOST_FUNCTION_TEMPLATE_PARMS
sl@0
   219
       >
sl@0
   220
      struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
sl@0
   221
      {
sl@0
   222
        typedef typename mpl::if_c<(is_void<R>::value),
sl@0
   223
                            BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
sl@0
   224
                            FunctionObj,
sl@0
   225
                            R BOOST_FUNCTION_COMMA
sl@0
   226
                            BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   227
                          >,
sl@0
   228
                          BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
sl@0
   229
                            FunctionObj,
sl@0
   230
                            R BOOST_FUNCTION_COMMA
sl@0
   231
                            BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   232
                          >
sl@0
   233
                       >::type type;
sl@0
   234
      };
sl@0
   235
sl@0
   236
      template<
sl@0
   237
        typename FunctionObj,
sl@0
   238
        typename R BOOST_FUNCTION_COMMA
sl@0
   239
        BOOST_FUNCTION_TEMPLATE_PARMS
sl@0
   240
       >
sl@0
   241
      struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
sl@0
   242
      {
sl@0
   243
        typedef typename mpl::if_c<(is_void<R>::value),
sl@0
   244
                            BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
sl@0
   245
                            FunctionObj,
sl@0
   246
                            R BOOST_FUNCTION_COMMA
sl@0
   247
                            BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   248
                          >,
sl@0
   249
                          BOOST_FUNCTION_FUNCTION_REF_INVOKER<
sl@0
   250
                            FunctionObj,
sl@0
   251
                            R BOOST_FUNCTION_COMMA
sl@0
   252
                            BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   253
                          >
sl@0
   254
                       >::type type;
sl@0
   255
      };
sl@0
   256
sl@0
   257
      /**
sl@0
   258
       * vtable for a specific boost::function instance.
sl@0
   259
       */
sl@0
   260
      template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
sl@0
   261
               typename Allocator>
sl@0
   262
      struct BOOST_FUNCTION_VTABLE : vtable_base
sl@0
   263
      {
sl@0
   264
#ifndef BOOST_NO_VOID_RETURNS
sl@0
   265
        typedef R         result_type;
sl@0
   266
#else
sl@0
   267
        typedef typename function_return_type<R>::type result_type;
sl@0
   268
#endif // BOOST_NO_VOID_RETURNS
sl@0
   269
sl@0
   270
        typedef result_type (*invoker_type)(function_buffer&
sl@0
   271
                                            BOOST_FUNCTION_COMMA
sl@0
   272
                                            BOOST_FUNCTION_TEMPLATE_ARGS);
sl@0
   273
sl@0
   274
        template<typename F>
sl@0
   275
        BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0)
sl@0
   276
        {
sl@0
   277
          init(f);
sl@0
   278
        }
sl@0
   279
sl@0
   280
        template<typename F>
sl@0
   281
        bool assign_to(F f, function_buffer& functor)
sl@0
   282
        {
sl@0
   283
          typedef typename get_function_tag<F>::type tag;
sl@0
   284
          return assign_to(f, functor, tag());
sl@0
   285
        }
sl@0
   286
sl@0
   287
        void clear(function_buffer& functor)
sl@0
   288
        {
sl@0
   289
          if (manager)
sl@0
   290
            manager(functor, functor, destroy_functor_tag);
sl@0
   291
        }
sl@0
   292
sl@0
   293
      private:
sl@0
   294
        template<typename F>
sl@0
   295
        void init(F f)
sl@0
   296
        {
sl@0
   297
          typedef typename get_function_tag<F>::type tag;
sl@0
   298
          init(f, tag());
sl@0
   299
        }
sl@0
   300
sl@0
   301
        // Function pointers
sl@0
   302
        template<typename FunctionPtr>
sl@0
   303
        void init(FunctionPtr /*f*/, function_ptr_tag)
sl@0
   304
        {
sl@0
   305
          typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
sl@0
   306
                             FunctionPtr,
sl@0
   307
                             R BOOST_FUNCTION_COMMA
sl@0
   308
                             BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   309
                           >::type
sl@0
   310
            actual_invoker_type;
sl@0
   311
sl@0
   312
          invoker = &actual_invoker_type::invoke;
sl@0
   313
          manager = &functor_manager<FunctionPtr, Allocator>::manage;
sl@0
   314
        }
sl@0
   315
sl@0
   316
        template<typename FunctionPtr>
sl@0
   317
        bool 
sl@0
   318
        assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
sl@0
   319
        {
sl@0
   320
          this->clear(functor);
sl@0
   321
          if (f) {
sl@0
   322
            // should be a reinterpret cast, but some compilers insist
sl@0
   323
            // on giving cv-qualifiers to free functions
sl@0
   324
            functor.func_ptr = (void (*)())(f);
sl@0
   325
            return true;
sl@0
   326
          } else {
sl@0
   327
            return false;
sl@0
   328
          }
sl@0
   329
        }
sl@0
   330
sl@0
   331
        // Member pointers
sl@0
   332
#if BOOST_FUNCTION_NUM_ARGS > 0
sl@0
   333
        template<typename MemberPtr>
sl@0
   334
        void init(MemberPtr f, member_ptr_tag)
sl@0
   335
        {
sl@0
   336
          // DPG TBD: Add explicit support for member function
sl@0
   337
          // objects, so we invoke through mem_fn() but we retain the
sl@0
   338
          // right target_type() values.
sl@0
   339
          this->init(mem_fn(f));
sl@0
   340
        }
sl@0
   341
sl@0
   342
        template<typename MemberPtr>
sl@0
   343
        bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag)
sl@0
   344
        {
sl@0
   345
          // DPG TBD: Add explicit support for member function
sl@0
   346
          // objects, so we invoke through mem_fn() but we retain the
sl@0
   347
          // right target_type() values.
sl@0
   348
          if (f) {
sl@0
   349
            this->assign_to(mem_fn(f), functor);
sl@0
   350
            return true;
sl@0
   351
          } else {
sl@0
   352
            return false;
sl@0
   353
          }
sl@0
   354
        }
sl@0
   355
#endif // BOOST_FUNCTION_NUM_ARGS > 0
sl@0
   356
sl@0
   357
        // Function objects
sl@0
   358
        template<typename FunctionObj>
sl@0
   359
        void init(FunctionObj /*f*/, function_obj_tag)
sl@0
   360
        {
sl@0
   361
          typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
sl@0
   362
                             FunctionObj,
sl@0
   363
                             R BOOST_FUNCTION_COMMA
sl@0
   364
                             BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   365
                           >::type
sl@0
   366
            actual_invoker_type;
sl@0
   367
sl@0
   368
          invoker = &actual_invoker_type::invoke;
sl@0
   369
          manager = &functor_manager<FunctionObj, Allocator>::manage;
sl@0
   370
        }
sl@0
   371
sl@0
   372
        // Assign to a function object using the small object optimization
sl@0
   373
        template<typename FunctionObj>
sl@0
   374
        void 
sl@0
   375
        assign_functor(FunctionObj f, function_buffer& functor, mpl::true_)
sl@0
   376
        {
sl@0
   377
          new ((void*)&functor.data) FunctionObj(f);
sl@0
   378
        }
sl@0
   379
sl@0
   380
        // Assign to a function object allocated on the heap.
sl@0
   381
        template<typename FunctionObj>
sl@0
   382
        void 
sl@0
   383
        assign_functor(FunctionObj f, function_buffer& functor, mpl::false_)
sl@0
   384
        {
sl@0
   385
#ifndef BOOST_NO_STD_ALLOCATOR
sl@0
   386
          typedef typename Allocator::template rebind<FunctionObj>::other
sl@0
   387
            allocator_type;
sl@0
   388
          typedef typename allocator_type::pointer pointer_type;
sl@0
   389
sl@0
   390
          allocator_type allocator;
sl@0
   391
          pointer_type copy = allocator.allocate(1);
sl@0
   392
          allocator.construct(copy, f);
sl@0
   393
sl@0
   394
          // Get back to the original pointer type
sl@0
   395
          functor.obj_ptr = static_cast<FunctionObj*>(copy);
sl@0
   396
#  else
sl@0
   397
          functor.obj_ptr = new FunctionObj(f);
sl@0
   398
#  endif // BOOST_NO_STD_ALLOCATOR
sl@0
   399
        }
sl@0
   400
sl@0
   401
        template<typename FunctionObj>
sl@0
   402
        bool 
sl@0
   403
        assign_to(FunctionObj f, function_buffer& functor, function_obj_tag)
sl@0
   404
        {
sl@0
   405
          if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
sl@0
   406
            assign_functor(f, functor, 
sl@0
   407
                           mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
sl@0
   408
            return true;
sl@0
   409
          } else {
sl@0
   410
            return false;
sl@0
   411
          }
sl@0
   412
        }
sl@0
   413
sl@0
   414
        // Reference to a function object
sl@0
   415
        template<typename FunctionObj>
sl@0
   416
        void 
sl@0
   417
        init(const reference_wrapper<FunctionObj>& /*f*/, function_obj_ref_tag)
sl@0
   418
        {
sl@0
   419
          typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
sl@0
   420
                             FunctionObj,
sl@0
   421
                             R BOOST_FUNCTION_COMMA
sl@0
   422
                             BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   423
                           >::type
sl@0
   424
            actual_invoker_type;
sl@0
   425
sl@0
   426
          invoker = &actual_invoker_type::invoke;
sl@0
   427
          manager = &reference_manager<FunctionObj>::get;
sl@0
   428
        }
sl@0
   429
sl@0
   430
        template<typename FunctionObj>
sl@0
   431
        bool 
sl@0
   432
        assign_to(const reference_wrapper<FunctionObj>& f, 
sl@0
   433
                  function_buffer& functor, function_obj_ref_tag)
sl@0
   434
        {
sl@0
   435
          if (!boost::detail::function::has_empty_target(f.get_pointer())) {
sl@0
   436
            // DPG TBD: We might need to detect constness of
sl@0
   437
            // FunctionObj to assign into obj_ptr or const_obj_ptr to
sl@0
   438
            // be truly legit, but no platform in existence makes
sl@0
   439
            // const void* different from void*.
sl@0
   440
            functor.const_obj_ptr = f.get_pointer();
sl@0
   441
            return true;
sl@0
   442
          } else {
sl@0
   443
            return false;
sl@0
   444
          }
sl@0
   445
        }
sl@0
   446
sl@0
   447
      public:
sl@0
   448
        invoker_type invoker;
sl@0
   449
      };
sl@0
   450
    } // end namespace function
sl@0
   451
  } // end namespace detail
sl@0
   452
sl@0
   453
  template<
sl@0
   454
    typename R BOOST_FUNCTION_COMMA
sl@0
   455
    BOOST_FUNCTION_TEMPLATE_PARMS,
sl@0
   456
    typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
sl@0
   457
  >
sl@0
   458
  class BOOST_FUNCTION_FUNCTION : public function_base
sl@0
   459
  {
sl@0
   460
  public:
sl@0
   461
#ifndef BOOST_NO_VOID_RETURNS
sl@0
   462
    typedef R         result_type;
sl@0
   463
#else
sl@0
   464
    typedef  typename boost::detail::function::function_return_type<R>::type
sl@0
   465
      result_type;
sl@0
   466
#endif // BOOST_NO_VOID_RETURNS
sl@0
   467
sl@0
   468
  private:
sl@0
   469
    typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
sl@0
   470
              R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Allocator>
sl@0
   471
      vtable_type;
sl@0
   472
sl@0
   473
    struct clear_type {};
sl@0
   474
sl@0
   475
  public:
sl@0
   476
    BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
sl@0
   477
sl@0
   478
    // add signature for boost::lambda
sl@0
   479
    template<typename Args>
sl@0
   480
    struct sig
sl@0
   481
    {
sl@0
   482
      typedef result_type type;
sl@0
   483
    };
sl@0
   484
sl@0
   485
#if BOOST_FUNCTION_NUM_ARGS == 1
sl@0
   486
    typedef T0 argument_type;
sl@0
   487
#elif BOOST_FUNCTION_NUM_ARGS == 2
sl@0
   488
    typedef T0 first_argument_type;
sl@0
   489
    typedef T1 second_argument_type;
sl@0
   490
#endif
sl@0
   491
sl@0
   492
    BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
sl@0
   493
    BOOST_FUNCTION_ARG_TYPES
sl@0
   494
sl@0
   495
    typedef Allocator allocator_type;
sl@0
   496
    typedef BOOST_FUNCTION_FUNCTION self_type;
sl@0
   497
sl@0
   498
    BOOST_FUNCTION_FUNCTION() : function_base() { }
sl@0
   499
sl@0
   500
    // MSVC chokes if the following two constructors are collapsed into
sl@0
   501
    // one with a default parameter.
sl@0
   502
    template<typename Functor>
sl@0
   503
    BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
sl@0
   504
#ifndef BOOST_NO_SFINAE
sl@0
   505
                            ,typename enable_if_c<
sl@0
   506
                            (boost::type_traits::ice_not<
sl@0
   507
                             (is_integral<Functor>::value)>::value),
sl@0
   508
                                        int>::type = 0
sl@0
   509
#endif // BOOST_NO_SFINAE
sl@0
   510
                            ) :
sl@0
   511
      function_base()
sl@0
   512
    {
sl@0
   513
      this->assign_to(f);
sl@0
   514
    }
sl@0
   515
sl@0
   516
#ifndef BOOST_NO_SFINAE
sl@0
   517
    BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
sl@0
   518
#else
sl@0
   519
    BOOST_FUNCTION_FUNCTION(int zero) : function_base()
sl@0
   520
    {
sl@0
   521
      BOOST_ASSERT(zero == 0);
sl@0
   522
    }
sl@0
   523
#endif
sl@0
   524
sl@0
   525
    BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
sl@0
   526
    {
sl@0
   527
      this->assign_to_own(f);
sl@0
   528
    }
sl@0
   529
sl@0
   530
    ~BOOST_FUNCTION_FUNCTION() { clear(); }
sl@0
   531
sl@0
   532
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
sl@0
   533
    // MSVC 6.0 and prior require all definitions to be inline, but
sl@0
   534
    // these definitions can become very costly.
sl@0
   535
    result_type operator()(BOOST_FUNCTION_PARMS) const
sl@0
   536
    {
sl@0
   537
      if (this->empty())
sl@0
   538
        boost::throw_exception(bad_function_call());
sl@0
   539
sl@0
   540
      return static_cast<vtable_type*>(vtable)->invoker
sl@0
   541
               (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
sl@0
   542
    }
sl@0
   543
#else
sl@0
   544
    result_type operator()(BOOST_FUNCTION_PARMS) const;
sl@0
   545
#endif
sl@0
   546
sl@0
   547
    // The distinction between when to use BOOST_FUNCTION_FUNCTION and
sl@0
   548
    // when to use self_type is obnoxious. MSVC cannot handle self_type as
sl@0
   549
    // the return type of these assignment operators, but Borland C++ cannot
sl@0
   550
    // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
sl@0
   551
    // construct.
sl@0
   552
    template<typename Functor>
sl@0
   553
#ifndef BOOST_NO_SFINAE
sl@0
   554
    typename enable_if_c<
sl@0
   555
               (boost::type_traits::ice_not<
sl@0
   556
                 (is_integral<Functor>::value)>::value),
sl@0
   557
               BOOST_FUNCTION_FUNCTION&>::type
sl@0
   558
#else
sl@0
   559
    BOOST_FUNCTION_FUNCTION&
sl@0
   560
#endif
sl@0
   561
    operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
sl@0
   562
    {
sl@0
   563
      this->clear();
sl@0
   564
      try {
sl@0
   565
        this->assign_to(f);
sl@0
   566
      } catch (...) {
sl@0
   567
        vtable = 0;
sl@0
   568
        throw;
sl@0
   569
      }
sl@0
   570
      return *this;
sl@0
   571
    }
sl@0
   572
sl@0
   573
#ifndef BOOST_NO_SFINAE
sl@0
   574
    BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
sl@0
   575
    {
sl@0
   576
      this->clear();
sl@0
   577
      return *this;
sl@0
   578
    }
sl@0
   579
#else
sl@0
   580
    BOOST_FUNCTION_FUNCTION& operator=(int zero)
sl@0
   581
    {
sl@0
   582
      BOOST_ASSERT(zero == 0);
sl@0
   583
      this->clear();
sl@0
   584
      return *this;
sl@0
   585
    }
sl@0
   586
#endif
sl@0
   587
sl@0
   588
    // Assignment from another BOOST_FUNCTION_FUNCTION
sl@0
   589
    BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
sl@0
   590
    {
sl@0
   591
      if (&f == this)
sl@0
   592
        return *this;
sl@0
   593
sl@0
   594
      this->clear();
sl@0
   595
      try {
sl@0
   596
        this->assign_to_own(f);
sl@0
   597
      } catch (...) {
sl@0
   598
        vtable = 0;
sl@0
   599
        throw;
sl@0
   600
      }
sl@0
   601
      return *this;
sl@0
   602
    }
sl@0
   603
sl@0
   604
    void swap(BOOST_FUNCTION_FUNCTION& other)
sl@0
   605
    {
sl@0
   606
      if (&other == this)
sl@0
   607
        return;
sl@0
   608
sl@0
   609
      BOOST_FUNCTION_FUNCTION tmp = *this;
sl@0
   610
      *this = other;
sl@0
   611
      other = tmp;
sl@0
   612
    }
sl@0
   613
sl@0
   614
    // Clear out a target, if there is one
sl@0
   615
    void clear()
sl@0
   616
    {
sl@0
   617
      if (vtable) {
sl@0
   618
        static_cast<vtable_type*>(vtable)->clear(this->functor);
sl@0
   619
        vtable = 0;
sl@0
   620
      }
sl@0
   621
    }
sl@0
   622
sl@0
   623
#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
sl@0
   624
    // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
sl@0
   625
    operator bool () const { return !this->empty(); }
sl@0
   626
#else
sl@0
   627
  private:
sl@0
   628
    struct dummy {
sl@0
   629
      void nonnull() {};
sl@0
   630
    };
sl@0
   631
sl@0
   632
    typedef void (dummy::*safe_bool)();
sl@0
   633
sl@0
   634
  public:
sl@0
   635
    operator safe_bool () const
sl@0
   636
      { return (this->empty())? 0 : &dummy::nonnull; }
sl@0
   637
sl@0
   638
    bool operator!() const
sl@0
   639
      { return this->empty(); }
sl@0
   640
#endif
sl@0
   641
sl@0
   642
  private:
sl@0
   643
    void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
sl@0
   644
    {
sl@0
   645
      if (!f.empty()) {
sl@0
   646
        this->vtable = f.vtable;
sl@0
   647
        f.vtable->manager(f.functor, this->functor,
sl@0
   648
                          boost::detail::function::clone_functor_tag);
sl@0
   649
      }
sl@0
   650
    }
sl@0
   651
sl@0
   652
    template<typename Functor>
sl@0
   653
    void assign_to(Functor f)
sl@0
   654
    {
sl@0
   655
      static vtable_type stored_vtable(f);
sl@0
   656
      if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
sl@0
   657
      else vtable = 0;
sl@0
   658
    }
sl@0
   659
  };
sl@0
   660
sl@0
   661
  template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
sl@0
   662
           typename Allocator>
sl@0
   663
  inline void swap(BOOST_FUNCTION_FUNCTION<
sl@0
   664
                     R BOOST_FUNCTION_COMMA
sl@0
   665
                     BOOST_FUNCTION_TEMPLATE_ARGS ,
sl@0
   666
                     Allocator
sl@0
   667
                   >& f1,
sl@0
   668
                   BOOST_FUNCTION_FUNCTION<
sl@0
   669
                     R BOOST_FUNCTION_COMMA
sl@0
   670
                     BOOST_FUNCTION_TEMPLATE_ARGS,
sl@0
   671
                     Allocator
sl@0
   672
                   >& f2)
sl@0
   673
  {
sl@0
   674
    f1.swap(f2);
sl@0
   675
  }
sl@0
   676
sl@0
   677
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
sl@0
   678
  template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
sl@0
   679
           typename Allocator>
sl@0
   680
  typename BOOST_FUNCTION_FUNCTION<
sl@0
   681
      R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
sl@0
   682
      Allocator>::result_type
sl@0
   683
   BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
sl@0
   684
sl@0
   685
                           Allocator>
sl@0
   686
  ::operator()(BOOST_FUNCTION_PARMS) const
sl@0
   687
  {
sl@0
   688
    if (this->empty())
sl@0
   689
      boost::throw_exception(bad_function_call());
sl@0
   690
sl@0
   691
    return static_cast<vtable_type*>(vtable)->invoker
sl@0
   692
             (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
sl@0
   693
  }
sl@0
   694
#endif
sl@0
   695
sl@0
   696
// Poison comparisons between boost::function objects of the same type.
sl@0
   697
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
sl@0
   698
         typename Allocator>
sl@0
   699
  void operator==(const BOOST_FUNCTION_FUNCTION<
sl@0
   700
                          R BOOST_FUNCTION_COMMA
sl@0
   701
                          BOOST_FUNCTION_TEMPLATE_ARGS ,
sl@0
   702
                          Allocator>&,
sl@0
   703
                  const BOOST_FUNCTION_FUNCTION<
sl@0
   704
                          R BOOST_FUNCTION_COMMA
sl@0
   705
                          BOOST_FUNCTION_TEMPLATE_ARGS ,
sl@0
   706
                  Allocator>&);
sl@0
   707
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
sl@0
   708
         typename Allocator>
sl@0
   709
  void operator!=(const BOOST_FUNCTION_FUNCTION<
sl@0
   710
                          R BOOST_FUNCTION_COMMA
sl@0
   711
                          BOOST_FUNCTION_TEMPLATE_ARGS ,
sl@0
   712
                          Allocator>&,
sl@0
   713
                  const BOOST_FUNCTION_FUNCTION<
sl@0
   714
                          R BOOST_FUNCTION_COMMA
sl@0
   715
                          BOOST_FUNCTION_TEMPLATE_ARGS ,
sl@0
   716
                  Allocator>&);
sl@0
   717
sl@0
   718
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
sl@0
   719
sl@0
   720
#if BOOST_FUNCTION_NUM_ARGS == 0
sl@0
   721
#define BOOST_FUNCTION_PARTIAL_SPEC R (void)
sl@0
   722
#else
sl@0
   723
#define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
sl@0
   724
#endif
sl@0
   725
sl@0
   726
template<typename R BOOST_FUNCTION_COMMA
sl@0
   727
         BOOST_FUNCTION_TEMPLATE_PARMS,
sl@0
   728
         typename Allocator>
sl@0
   729
class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
sl@0
   730
  : public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   731
                                   BOOST_FUNCTION_COMMA Allocator>
sl@0
   732
{
sl@0
   733
  typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   734
                                  BOOST_FUNCTION_COMMA Allocator> base_type;
sl@0
   735
  typedef function self_type;
sl@0
   736
sl@0
   737
  struct clear_type {};
sl@0
   738
sl@0
   739
public:
sl@0
   740
  typedef typename base_type::allocator_type allocator_type;
sl@0
   741
sl@0
   742
  function() : base_type() {}
sl@0
   743
sl@0
   744
  template<typename Functor>
sl@0
   745
  function(Functor f
sl@0
   746
#ifndef BOOST_NO_SFINAE
sl@0
   747
           ,typename enable_if_c<
sl@0
   748
                            (boost::type_traits::ice_not<
sl@0
   749
                          (is_integral<Functor>::value)>::value),
sl@0
   750
                       int>::type = 0
sl@0
   751
#endif
sl@0
   752
           ) :
sl@0
   753
    base_type(f)
sl@0
   754
  {
sl@0
   755
  }
sl@0
   756
sl@0
   757
#ifndef BOOST_NO_SFINAE
sl@0
   758
  function(clear_type*) : base_type() {}
sl@0
   759
#endif
sl@0
   760
sl@0
   761
  function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
sl@0
   762
sl@0
   763
  function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
sl@0
   764
sl@0
   765
  self_type& operator=(const self_type& f)
sl@0
   766
  {
sl@0
   767
    self_type(f).swap(*this);
sl@0
   768
    return *this;
sl@0
   769
  }
sl@0
   770
sl@0
   771
  template<typename Functor>
sl@0
   772
#ifndef BOOST_NO_SFINAE
sl@0
   773
  typename enable_if_c<
sl@0
   774
                            (boost::type_traits::ice_not<
sl@0
   775
                         (is_integral<Functor>::value)>::value),
sl@0
   776
                      self_type&>::type
sl@0
   777
#else
sl@0
   778
  self_type&
sl@0
   779
#endif
sl@0
   780
  operator=(Functor f)
sl@0
   781
  {
sl@0
   782
    self_type(f).swap(*this);
sl@0
   783
    return *this;
sl@0
   784
  }
sl@0
   785
sl@0
   786
#ifndef BOOST_NO_SFINAE
sl@0
   787
  self_type& operator=(clear_type*)
sl@0
   788
  {
sl@0
   789
    this->clear();
sl@0
   790
    return *this;
sl@0
   791
  }
sl@0
   792
#endif
sl@0
   793
sl@0
   794
  self_type& operator=(const base_type& f)
sl@0
   795
  {
sl@0
   796
    self_type(f).swap(*this);
sl@0
   797
    return *this;
sl@0
   798
  }
sl@0
   799
};
sl@0
   800
sl@0
   801
#ifdef BOOST_MSVC
sl@0
   802
# pragma warning(pop)
sl@0
   803
#endif
sl@0
   804
sl@0
   805
#undef BOOST_FUNCTION_PARTIAL_SPEC
sl@0
   806
#endif // have partial specialization
sl@0
   807
sl@0
   808
} // end namespace boost
sl@0
   809
sl@0
   810
#ifdef BOOST_MSVC
sl@0
   811
# pragma warning(pop)
sl@0
   812
#endif
sl@0
   813
sl@0
   814
// Cleanup after ourselves...
sl@0
   815
#undef BOOST_FUNCTION_VTABLE
sl@0
   816
#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
sl@0
   817
#undef BOOST_FUNCTION_COMMA
sl@0
   818
#undef BOOST_FUNCTION_FUNCTION
sl@0
   819
#undef BOOST_FUNCTION_FUNCTION_INVOKER
sl@0
   820
#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
sl@0
   821
#undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
sl@0
   822
#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
sl@0
   823
#undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
sl@0
   824
#undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
sl@0
   825
#undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
sl@0
   826
#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
sl@0
   827
#undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
sl@0
   828
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
sl@0
   829
#undef BOOST_FUNCTION_TEMPLATE_PARMS
sl@0
   830
#undef BOOST_FUNCTION_TEMPLATE_ARGS
sl@0
   831
#undef BOOST_FUNCTION_PARMS
sl@0
   832
#undef BOOST_FUNCTION_PARM
sl@0
   833
#undef BOOST_FUNCTION_ARGS
sl@0
   834
#undef BOOST_FUNCTION_ARG_TYPE
sl@0
   835
#undef BOOST_FUNCTION_ARG_TYPES
sl@0
   836
#undef BOOST_FUNCTION_VOID_RETURN_TYPE
sl@0
   837
#undef BOOST_FUNCTION_RETURN