Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/function/function_base.hpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

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