]> git.lyx.org Git - lyx.git/blob - boost/boost/function/function_base.hpp
Update in-tree boost to latest from boost 1.34 cvs.
[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             functor_type* out_functor = 
288               reinterpret_cast<functor_type*>(&out_buffer.data);
289             // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
290             out_functor->~Functor();
291           } else /* op == check_functor_type_tag */ {
292             const std::type_info& check_type = 
293               *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
294             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
295               out_buffer.obj_ptr = &in_buffer.data;
296             else
297               out_buffer.obj_ptr = 0;
298           }
299         }
300         
301         // Function objects that require heap allocation
302         static inline void
303         manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
304                 functor_manager_operation_type op, mpl::false_)
305         {
306 #ifndef BOOST_NO_STD_ALLOCATOR
307           typedef typename Allocator::template rebind<functor_type>::other
308             allocator_type;
309           typedef typename allocator_type::pointer pointer_type;
310 #else
311           typedef functor_type* pointer_type;
312 #endif // BOOST_NO_STD_ALLOCATOR
313
314 #  ifndef BOOST_NO_STD_ALLOCATOR
315           allocator_type allocator;
316 #  endif // BOOST_NO_STD_ALLOCATOR
317
318           if (op == clone_functor_tag) {
319             // GCC 2.95.3 gets the CV qualifiers wrong here, so we
320             // can't do the static_cast that we should do.
321             const functor_type* f =
322               (const functor_type*)(in_buffer.obj_ptr);
323
324             // Clone the functor
325 #  ifndef BOOST_NO_STD_ALLOCATOR
326             pointer_type copy = allocator.allocate(1);
327             allocator.construct(copy, *f);
328
329             // Get back to the original pointer type
330             functor_type* new_f = static_cast<functor_type*>(copy);
331 #  else
332             functor_type* new_f = new functor_type(*f);
333 #  endif // BOOST_NO_STD_ALLOCATOR
334             out_buffer.obj_ptr = new_f;
335           } else if (op == destroy_functor_tag) {
336             /* Cast from the void pointer to the functor pointer type */
337             functor_type* f =
338               static_cast<functor_type*>(out_buffer.obj_ptr);
339
340 #  ifndef BOOST_NO_STD_ALLOCATOR
341             /* Cast from the functor pointer type to the allocator's pointer
342                type */
343             pointer_type victim = static_cast<pointer_type>(f);
344
345             // Destroy and deallocate the functor
346             allocator.destroy(victim);
347             allocator.deallocate(victim, 1);
348 #  else
349             delete f;
350 #  endif // BOOST_NO_STD_ALLOCATOR
351             out_buffer.obj_ptr = 0;
352           } else /* op == check_functor_type_tag */ {
353             const std::type_info& check_type = 
354               *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
355             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
356               out_buffer.obj_ptr = in_buffer.obj_ptr;
357             else
358               out_buffer.obj_ptr = 0;
359           }
360         }
361
362         // For function objects, we determine whether the function
363         // object can use the small-object optimization buffer or
364         // whether we need to allocate it on the heap.
365         static inline void
366         manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
367                 functor_manager_operation_type op, function_obj_tag)
368         {
369           manager(in_buffer, out_buffer, op,
370                   mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
371         }
372
373       public:
374         /* Dispatch to an appropriate manager based on whether we have a
375            function pointer or a function object pointer. */
376         static inline void
377         manage(const function_buffer& in_buffer, function_buffer& out_buffer, 
378                functor_manager_operation_type op)
379         {
380           typedef typename get_function_tag<functor_type>::type tag_type;
381           switch (op) {
382           case get_functor_type_tag:
383             out_buffer.const_obj_ptr = &typeid(functor_type);
384             return;
385
386           default:
387             manager(in_buffer, out_buffer, op, tag_type());
388             return;
389           }
390         }
391       };
392
393       // A type that is only used for comparisons against zero
394       struct useless_clear_type {};
395
396 #ifdef BOOST_NO_SFINAE
397       // These routines perform comparisons between a Boost.Function
398       // object and an arbitrary function object (when the last
399       // parameter is mpl::bool_<false>) or against zero (when the
400       // last parameter is mpl::bool_<true>). They are only necessary
401       // for compilers that don't support SFINAE.
402       template<typename Function, typename Functor>
403         bool
404         compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
405         { return f.empty(); }
406
407       template<typename Function, typename Functor>
408         bool
409         compare_not_equal(const Function& f, const Functor&, int,
410                           mpl::bool_<true>)
411         { return !f.empty(); }
412
413       template<typename Function, typename Functor>
414         bool
415         compare_equal(const Function& f, const Functor& g, long,
416                       mpl::bool_<false>)
417         {
418           if (const Functor* fp = f.template target<Functor>())
419             return function_equal(*fp, g);
420           else return false;
421         }
422
423       template<typename Function, typename Functor>
424         bool
425         compare_equal(const Function& f, const reference_wrapper<Functor>& g,
426                       int, mpl::bool_<false>)
427         {
428           if (const Functor* fp = f.template target<Functor>())
429             return fp == g.get_pointer();
430           else return false;
431         }
432
433       template<typename Function, typename Functor>
434         bool
435         compare_not_equal(const Function& f, const Functor& g, long,
436                           mpl::bool_<false>)
437         {
438           if (const Functor* fp = f.template target<Functor>())
439             return !function_equal(*fp, g);
440           else return true;
441         }
442
443       template<typename Function, typename Functor>
444         bool
445         compare_not_equal(const Function& f,
446                           const reference_wrapper<Functor>& g, int,
447                           mpl::bool_<false>)
448         {
449           if (const Functor* fp = f.template target<Functor>())
450             return fp != g.get_pointer();
451           else return true;
452         }
453 #endif // BOOST_NO_SFINAE
454
455       /**
456        * Stores the "manager" portion of the vtable for a
457        * boost::function object.
458        */
459       struct vtable_base
460       {
461         vtable_base() : manager(0) { }
462         void (*manager)(const function_buffer& in_buffer, 
463                         function_buffer& out_buffer, 
464                         functor_manager_operation_type op);
465       };
466     } // end namespace function
467   } // end namespace detail
468
469 /**
470  * The function_base class contains the basic elements needed for the
471  * function1, function2, function3, etc. classes. It is common to all
472  * functions (and as such can be used to tell if we have one of the
473  * functionN objects).
474  */
475 class function_base
476 {
477 public:
478   function_base() : vtable(0) { }
479
480   /** Determine if the function is empty (i.e., has no target). */
481   bool empty() const { return !vtable; }
482
483   /** Retrieve the type of the stored function object, or typeid(void)
484       if this is empty. */
485   const std::type_info& target_type() const
486   {
487     if (!vtable) return typeid(void);
488
489     detail::function::function_buffer type;
490     vtable->manager(functor, type, detail::function::get_functor_type_tag);
491     return *static_cast<const std::type_info*>(type.const_obj_ptr);
492   }
493
494   template<typename Functor>
495     Functor* target()
496     {
497       if (!vtable) return 0;
498
499       detail::function::function_buffer type_result;
500       type_result.const_obj_ptr = &typeid(Functor);
501       vtable->manager(functor, type_result, 
502                       detail::function::check_functor_type_tag);
503       return static_cast<Functor*>(type_result.obj_ptr);
504     }
505
506   template<typename Functor>
507 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
508     const Functor* target( Functor * = 0 ) const
509 #else
510     const Functor* target() const
511 #endif
512     {
513       if (!vtable) return 0;
514
515       detail::function::function_buffer type_result;
516       type_result.const_obj_ptr = &typeid(Functor);
517       vtable->manager(functor, type_result, 
518                       detail::function::check_functor_type_tag);
519       // GCC 2.95.3 gets the CV qualifiers wrong here, so we
520       // can't do the static_cast that we should do.
521       return (const Functor*)(type_result.obj_ptr);
522     }
523
524   template<typename F>
525     bool contains(const F& f) const
526     {
527 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
528       if (const F* fp = this->target( (F*)0 ))
529 #else
530       if (const F* fp = this->template target<F>())
531 #endif
532       {
533         return function_equal(*fp, f);
534       } else {
535         return false;
536       }
537     }
538
539 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
540   // GCC 3.3 and newer cannot copy with the global operator==, due to
541   // problems with instantiation of function return types before it
542   // has been verified that the argument types match up.
543   template<typename Functor>
544     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
545     operator==(Functor g) const
546     {
547       if (const Functor* fp = target<Functor>())
548         return function_equal(*fp, g);
549       else return false;
550     }
551
552   template<typename Functor>
553     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
554     operator!=(Functor g) const
555     {
556       if (const Functor* fp = target<Functor>())
557         return !function_equal(*fp, g);
558       else return true;
559     }
560 #endif
561
562 public: // should be protected, but GCC 2.95.3 will fail to allow access
563   detail::function::vtable_base* vtable;
564   mutable detail::function::function_buffer functor;
565 };
566
567 /**
568  * The bad_function_call exception class is thrown when a boost::function
569  * object is invoked
570  */
571 class bad_function_call : public std::runtime_error
572 {
573 public:
574   bad_function_call() : std::runtime_error("call to empty boost::function") {}
575 };
576
577 #ifndef BOOST_NO_SFINAE
578 inline bool operator==(const function_base& f,
579                        detail::function::useless_clear_type*)
580 {
581   return f.empty();
582 }
583
584 inline bool operator!=(const function_base& f,
585                        detail::function::useless_clear_type*)
586 {
587   return !f.empty();
588 }
589
590 inline bool operator==(detail::function::useless_clear_type*,
591                        const function_base& f)
592 {
593   return f.empty();
594 }
595
596 inline bool operator!=(detail::function::useless_clear_type*,
597                        const function_base& f)
598 {
599   return !f.empty();
600 }
601 #endif
602
603 #ifdef BOOST_NO_SFINAE
604 // Comparisons between boost::function objects and arbitrary function objects
605 template<typename Functor>
606   inline bool operator==(const function_base& f, Functor g)
607   {
608     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
609     return detail::function::compare_equal(f, g, 0, integral());
610   }
611
612 template<typename Functor>
613   inline bool operator==(Functor g, const function_base& f)
614   {
615     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
616     return detail::function::compare_equal(f, g, 0, integral());
617   }
618
619 template<typename Functor>
620   inline bool operator!=(const function_base& f, Functor g)
621   {
622     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
623     return detail::function::compare_not_equal(f, g, 0, integral());
624   }
625
626 template<typename Functor>
627   inline bool operator!=(Functor g, const function_base& f)
628   {
629     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
630     return detail::function::compare_not_equal(f, g, 0, integral());
631   }
632 #else
633
634 #  if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
635 // Comparisons between boost::function objects and arbitrary function
636 // objects. GCC 3.3 and before has an obnoxious bug that prevents this
637 // from working.
638 template<typename Functor>
639   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
640   operator==(const function_base& f, Functor g)
641   {
642     if (const Functor* fp = f.template target<Functor>())
643       return function_equal(*fp, g);
644     else return false;
645   }
646
647 template<typename Functor>
648   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
649   operator==(Functor g, const function_base& f)
650   {
651     if (const Functor* fp = f.template target<Functor>())
652       return function_equal(g, *fp);
653     else return false;
654   }
655
656 template<typename Functor>
657   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
658   operator!=(const function_base& f, Functor g)
659   {
660     if (const Functor* fp = f.template target<Functor>())
661       return !function_equal(*fp, g);
662     else return true;
663   }
664
665 template<typename Functor>
666   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
667   operator!=(Functor g, const function_base& f)
668   {
669     if (const Functor* fp = f.template target<Functor>())
670       return !function_equal(g, *fp);
671     else return true;
672   }
673 #  endif
674
675 template<typename Functor>
676   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
677   operator==(const function_base& f, reference_wrapper<Functor> g)
678   {
679     if (const Functor* fp = f.template target<Functor>())
680       return fp == g.get_pointer();
681     else return false;
682   }
683
684 template<typename Functor>
685   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
686   operator==(reference_wrapper<Functor> g, const function_base& f)
687   {
688     if (const Functor* fp = f.template target<Functor>())
689       return g.get_pointer() == fp;
690     else return false;
691   }
692
693 template<typename Functor>
694   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
695   operator!=(const function_base& f, reference_wrapper<Functor> g)
696   {
697     if (const Functor* fp = f.template target<Functor>())
698       return fp != g.get_pointer();
699     else return true;
700   }
701
702 template<typename Functor>
703   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
704   operator!=(reference_wrapper<Functor> g, const function_base& f)
705   {
706     if (const Functor* fp = f.template target<Functor>())
707       return g.get_pointer() != fp;
708     else return true;
709   }
710
711 #endif // Compiler supporting SFINAE
712
713 namespace detail {
714   namespace function {
715     inline bool has_empty_target(const function_base* f)
716     {
717       return f->empty();
718     }
719
720 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
721     inline bool has_empty_target(const void*)
722     {
723       return false;
724     }
725 #else
726     inline bool has_empty_target(...)
727     {
728       return false;
729     }
730 #endif
731   } // end namespace function
732 } // end namespace detail
733 } // end namespace boost
734
735 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
736 #undef BOOST_FUNCTION_COMPARE_TYPE_ID
737
738 #endif // BOOST_FUNCTION_BASE_HEADER