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