]> git.lyx.org Git - lyx.git/blob - boost/boost/function/function_base.hpp
Update to latest from boost 1.34 cvs release branch
[lyx.git] / boost / boost / function / function_base.hpp
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.
55 namespace 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)
81 namespace 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>
85 class function_base;
86
87 template<typename Signature,
88          typename Allocator = std::allocator<function_base> >
89 class function;
90 #else
91 template<typename Signature, typename Allocator = std::allocator<void> >
92 class function;
93 #endif
94
95 template<typename Signature, typename Allocator>
96 inline 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
105 namespace 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  */
473 class function_base
474 {
475 public:
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
560 public: // 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  */
569 class bad_function_call : public std::runtime_error
570 {
571 public:
572   bad_function_call() : std::runtime_error("call to empty boost::function") {}
573 };
574
575 #ifndef BOOST_NO_SFINAE
576 inline bool operator==(const function_base& f,
577                        detail::function::useless_clear_type*)
578 {
579   return f.empty();
580 }
581
582 inline bool operator!=(const function_base& f,
583                        detail::function::useless_clear_type*)
584 {
585   return !f.empty();
586 }
587
588 inline bool operator==(detail::function::useless_clear_type*,
589                        const function_base& f)
590 {
591   return f.empty();
592 }
593
594 inline 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
603 template<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
610 template<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
617 template<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
624 template<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.
636 template<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
645 template<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
654 template<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
663 template<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
673 template<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
682 template<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
691 template<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
700 template<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
711 namespace 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