]> git.lyx.org Git - lyx.git/blob - boost/boost/function/function_base.hpp
Upgrade to boost 1.33.1
[lyx.git] / boost / boost / function / function_base.hpp
1 // Boost.Function library
2
3 //  Copyright Douglas Gregor 2001-2004. 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/type_traits/is_stateless.hpp>
23 #include <boost/ref.hpp>
24 #include <boost/pending/ct_if.hpp>
25 #include <boost/detail/workaround.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       /**
109        * A union of a function pointer and a void pointer. This is necessary
110        * because 5.2.10/6 allows reinterpret_cast<> to safely cast between
111        * function pointer types and 5.2.9/10 allows static_cast<> to safely
112        * cast between a void pointer and an object pointer. But it is not legal
113        * to cast between a function pointer and a void* (in either direction),
114        * so function requires a union of the two. */
115       union any_pointer
116       {
117         void* obj_ptr;
118         const void* const_obj_ptr;
119         void (*func_ptr)();
120         char data[1];
121       };
122
123       inline any_pointer make_any_pointer(void* o)
124       {
125         any_pointer p;
126         p.obj_ptr = o;
127         return p;
128       }
129
130       inline any_pointer make_any_pointer(const void* o)
131       {
132         any_pointer p;
133         p.const_obj_ptr = o;
134         return p;
135       }
136
137       inline any_pointer make_any_pointer(void (*f)())
138       {
139         any_pointer p;
140         p.func_ptr = f;
141         return p;
142       }
143
144       /**
145        * The unusable class is a placeholder for unused function arguments
146        * It is also completely unusable except that it constructable from
147        * anything. This helps compilers without partial specialization to
148        * handle Boost.Function objects returning void.
149        */
150       struct unusable
151       {
152         unusable() {}
153         template<typename T> unusable(const T&) {}
154       };
155
156       /* Determine the return type. This supports compilers that do not support
157        * void returns or partial specialization by silently changing the return
158        * type to "unusable".
159        */
160       template<typename T> struct function_return_type { typedef T type; };
161
162       template<>
163       struct function_return_type<void>
164       {
165         typedef unusable type;
166       };
167
168       // The operation type to perform on the given functor/function pointer
169       enum functor_manager_operation_type {
170         clone_functor_tag,
171         destroy_functor_tag,
172         check_functor_type_tag
173       };
174
175       // Tags used to decide between different types of functions
176       struct function_ptr_tag {};
177       struct function_obj_tag {};
178       struct member_ptr_tag {};
179       struct function_obj_ref_tag {};
180       struct stateless_function_obj_tag {};
181
182       template<typename F>
183       class get_function_tag
184       {
185         typedef typename ct_if<(is_pointer<F>::value),
186                             function_ptr_tag,
187                             function_obj_tag>::type ptr_or_obj_tag;
188
189         typedef typename ct_if<(is_member_pointer<F>::value),
190                             member_ptr_tag,
191                             ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
192
193         typedef typename ct_if<(is_reference_wrapper<F>::value),
194                              function_obj_ref_tag,
195                              ptr_or_obj_or_mem_tag>::type or_ref_tag;
196
197       public:
198         typedef typename ct_if<(is_stateless<F>::value),
199                             stateless_function_obj_tag,
200                             or_ref_tag>::type type;
201       };
202
203       // The trivial manager does nothing but return the same pointer (if we
204       // are cloning) or return the null pointer (if we are deleting).
205       template<typename F>
206       struct trivial_manager
207       {
208         static inline any_pointer
209         get(any_pointer f, functor_manager_operation_type op)
210         {
211           switch (op) {
212           case clone_functor_tag: return f;
213
214           case destroy_functor_tag:
215             return make_any_pointer(reinterpret_cast<void*>(0));
216
217           case check_functor_type_tag:
218             {
219               std::type_info* t = static_cast<std::type_info*>(f.obj_ptr);
220               return BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(F), *t)?
221                 f
222                 : make_any_pointer(reinterpret_cast<void*>(0));
223             }
224           }
225
226           // Clears up a warning with GCC 3.2.3
227           return make_any_pointer(reinterpret_cast<void*>(0));
228         }
229       };
230
231       /**
232        * The functor_manager class contains a static function "manage" which
233        * can clone or destroy the given function/function object pointer.
234        */
235       template<typename Functor, typename Allocator>
236       struct functor_manager
237       {
238       private:
239         typedef Functor functor_type;
240
241         // For function pointers, the manager is trivial
242         static inline any_pointer
243         manager(any_pointer function_ptr,
244                 functor_manager_operation_type op,
245                 function_ptr_tag)
246         {
247           if (op == clone_functor_tag)
248             return function_ptr;
249           else
250             return make_any_pointer(static_cast<void (*)()>(0));
251         }
252
253         // For function object pointers, we clone the pointer to each
254         // function has its own version.
255         static inline any_pointer
256         manager(any_pointer function_obj_ptr,
257                 functor_manager_operation_type op,
258                 function_obj_tag)
259         {
260 #ifndef BOOST_NO_STD_ALLOCATOR
261         typedef typename Allocator::template rebind<functor_type>::other
262           allocator_type;
263         typedef typename allocator_type::pointer pointer_type;
264 #else
265         typedef functor_type* pointer_type;
266 #endif // BOOST_NO_STD_ALLOCATOR
267
268 #  ifndef BOOST_NO_STD_ALLOCATOR
269           allocator_type allocator;
270 #  endif // BOOST_NO_STD_ALLOCATOR
271
272           if (op == clone_functor_tag) {
273             functor_type* f =
274               static_cast<functor_type*>(function_obj_ptr.obj_ptr);
275
276             // Clone the functor
277 #  ifndef BOOST_NO_STD_ALLOCATOR
278             pointer_type copy = allocator.allocate(1);
279             allocator.construct(copy, *f);
280
281             // Get back to the original pointer type
282             functor_type* new_f = static_cast<functor_type*>(copy);
283 #  else
284             functor_type* new_f = new functor_type(*f);
285 #  endif // BOOST_NO_STD_ALLOCATOR
286             return make_any_pointer(static_cast<void*>(new_f));
287           }
288           else {
289             /* Cast from the void pointer to the functor pointer type */
290             functor_type* f =
291               reinterpret_cast<functor_type*>(function_obj_ptr.obj_ptr);
292
293 #  ifndef BOOST_NO_STD_ALLOCATOR
294             /* Cast from the functor pointer type to the allocator's pointer
295                type */
296             pointer_type victim = static_cast<pointer_type>(f);
297
298             // Destroy and deallocate the functor
299             allocator.destroy(victim);
300             allocator.deallocate(victim, 1);
301 #  else
302             delete f;
303 #  endif // BOOST_NO_STD_ALLOCATOR
304
305             return make_any_pointer(static_cast<void*>(0));
306           }
307         }
308       public:
309         /* Dispatch to an appropriate manager based on whether we have a
310            function pointer or a function object pointer. */
311         static any_pointer
312         manage(any_pointer functor_ptr, functor_manager_operation_type op)
313         {
314           if (op == check_functor_type_tag) {
315             std::type_info* type =
316               static_cast<std::type_info*>(functor_ptr.obj_ptr);
317             return (BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(Functor), *type)?
318                     functor_ptr
319                     : make_any_pointer(reinterpret_cast<void*>(0)));
320           }
321           else {
322             typedef typename get_function_tag<functor_type>::type tag_type;
323             return manager(functor_ptr, op, tag_type());
324           }
325         }
326       };
327
328       // A type that is only used for comparisons against zero
329       struct useless_clear_type {};
330
331 #ifdef BOOST_NO_SFINAE
332       // These routines perform comparisons between a Boost.Function
333       // object and an arbitrary function object (when the last
334       // parameter is mpl::bool_<false>) or against zero (when the
335       // last parameter is mpl::bool_<true>). They are only necessary
336       // for compilers that don't support SFINAE.
337       template<typename Function, typename Functor>
338         bool
339         compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
340         { return f.empty(); }
341
342       template<typename Function, typename Functor>
343         bool
344         compare_not_equal(const Function& f, const Functor&, int,
345                           mpl::bool_<true>)
346         { return !f.empty(); }
347
348       template<typename Function, typename Functor>
349         bool
350         compare_equal(const Function& f, const Functor& g, long,
351                       mpl::bool_<false>)
352         {
353           if (const Functor* fp = f.template target<Functor>())
354             return function_equal(*fp, g);
355           else return false;
356         }
357
358       template<typename Function, typename Functor>
359         bool
360         compare_equal(const Function& f, const reference_wrapper<Functor>& g,
361                       int, mpl::bool_<false>)
362         {
363           if (const Functor* fp = f.template target<Functor>())
364             return fp == g.get_pointer();
365           else return false;
366         }
367
368       template<typename Function, typename Functor>
369         bool
370         compare_not_equal(const Function& f, const Functor& g, long,
371                           mpl::bool_<false>)
372         {
373           if (const Functor* fp = f.template target<Functor>())
374             return !function_equal(*fp, g);
375           else return true;
376         }
377
378       template<typename Function, typename Functor>
379         bool
380         compare_not_equal(const Function& f,
381                           const reference_wrapper<Functor>& g, int,
382                           mpl::bool_<false>)
383         {
384           if (const Functor* fp = f.template target<Functor>())
385             return fp != g.get_pointer();
386           else return true;
387         }
388 #endif // BOOST_NO_SFINAE
389     } // end namespace function
390   } // end namespace detail
391
392 /**
393  * The function_base class contains the basic elements needed for the
394  * function1, function2, function3, etc. classes. It is common to all
395  * functions (and as such can be used to tell if we have one of the
396  * functionN objects).
397  */
398 class function_base
399 {
400 public:
401   function_base() : manager(0)
402   {
403     functor.obj_ptr = 0;
404   }
405
406   // Is this function empty?
407   bool empty() const { return !manager; }
408
409   template<typename Functor>
410     Functor* target()
411     {
412       if (!manager) return 0;
413
414       detail::function::any_pointer result =
415         manager(detail::function::make_any_pointer(&typeid(Functor)),
416                 detail::function::check_functor_type_tag);
417       if (!result.obj_ptr) return 0;
418       else {
419         typedef typename detail::function::get_function_tag<Functor>::type tag;
420         return get_functor_pointer<Functor>(tag(), 0);
421       }
422     }
423
424   template<typename Functor>
425
426 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
427     const Functor* target( Functor * = 0 ) const
428 #else
429     const Functor* target() const
430 #endif
431     {
432       if (!manager) return 0;
433
434       detail::function::any_pointer result =
435         manager(detail::function::make_any_pointer(&typeid(Functor)),
436                 detail::function::check_functor_type_tag);
437       if (!result.obj_ptr) return 0;
438       else {
439         typedef typename detail::function::get_function_tag<Functor>::type tag;
440
441 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
442         return get_functor_pointer(tag(), 0, (Functor*)0);
443 #else
444         return get_functor_pointer<Functor>(tag(), 0);
445 #endif
446       }
447     }
448
449   template<typename F>
450     bool contains(const F& f) const
451     {
452 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
453       if (const F* fp = this->target( (F*)0 )) {
454 #else
455       if (const F* fp = this->template target<F>()) {
456 #endif
457         return function_equal(*fp, f);
458       } else {
459         return false;
460       }
461     }
462
463 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
464   // GCC 3.3 and newer cannot copy with the global operator==, due to
465   // problems with instantiation of function return types before it
466   // has been verified that the argument types match up.
467   template<typename Functor>
468     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
469     operator==(Functor g) const
470     {
471       if (const Functor* fp = target<Functor>())
472         return function_equal(*fp, g);
473       else return false;
474     }
475
476   template<typename Functor>
477     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
478     operator!=(Functor g) const
479     {
480       if (const Functor* fp = target<Functor>())
481         return !function_equal(*fp, g);
482       else return true;
483     }
484 #endif
485
486 public: // should be protected, but GCC 2.95.3 will fail to allow access
487   detail::function::any_pointer (*manager)(
488     detail::function::any_pointer,
489     detail::function::functor_manager_operation_type);
490   detail::function::any_pointer functor;
491
492 private:
493   template<typename Functor>
494 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
495     Functor* get_functor_pointer(detail::function::function_ptr_tag, int, Functor * = 0)
496 #else
497     Functor* get_functor_pointer(detail::function::function_ptr_tag, int)
498 #endif
499     { return reinterpret_cast<Functor*>(&functor.func_ptr); }
500
501   template<typename Functor, typename Tag>
502 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
503     Functor* get_functor_pointer(Tag, long, Functor * = 0)
504 #else
505     Functor* get_functor_pointer(Tag, long)
506 #endif
507     { return static_cast<Functor*>(functor.obj_ptr); }
508
509   template<typename Functor>
510     const Functor*
511 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
512     get_functor_pointer(detail::function::function_ptr_tag, int, Functor * = 0) const
513 #else
514     get_functor_pointer(detail::function::function_ptr_tag, int) const
515 #endif
516     { return reinterpret_cast<const Functor*>(&functor.func_ptr); }
517
518   template<typename Functor, typename Tag>
519 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
520     const Functor* get_functor_pointer(Tag, long, Functor * = 0) const
521 #else
522     const Functor* get_functor_pointer(Tag, long) const
523 #endif
524     { return static_cast<const Functor*>(functor.const_obj_ptr); }
525 };
526
527 /**
528  * The bad_function_call exception class is thrown when a boost::function
529  * object is invoked
530  */
531 class bad_function_call : public std::runtime_error
532 {
533 public:
534   bad_function_call() : std::runtime_error("call to empty boost::function") {}
535 };
536
537 #ifndef BOOST_NO_SFINAE
538 inline bool operator==(const function_base& f,
539                        detail::function::useless_clear_type*)
540 {
541   return f.empty();
542 }
543
544 inline bool operator!=(const function_base& f,
545                        detail::function::useless_clear_type*)
546 {
547   return !f.empty();
548 }
549
550 inline bool operator==(detail::function::useless_clear_type*,
551                        const function_base& f)
552 {
553   return f.empty();
554 }
555
556 inline bool operator!=(detail::function::useless_clear_type*,
557                        const function_base& f)
558 {
559   return !f.empty();
560 }
561 #endif
562
563 #ifdef BOOST_NO_SFINAE
564 // Comparisons between boost::function objects and arbitrary function objects
565 template<typename Functor>
566   inline bool operator==(const function_base& f, Functor g)
567   {
568     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
569     return detail::function::compare_equal(f, g, 0, integral());
570   }
571
572 template<typename Functor>
573   inline bool operator==(Functor g, const function_base& f)
574   {
575     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
576     return detail::function::compare_equal(f, g, 0, integral());
577   }
578
579 template<typename Functor>
580   inline bool operator!=(const function_base& f, Functor g)
581   {
582     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
583     return detail::function::compare_not_equal(f, g, 0, integral());
584   }
585
586 template<typename Functor>
587   inline bool operator!=(Functor g, const function_base& f)
588   {
589     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
590     return detail::function::compare_not_equal(f, g, 0, integral());
591   }
592 #else
593
594 #  if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
595 // Comparisons between boost::function objects and arbitrary function
596 // objects. GCC 3.3 and before has an obnoxious bug that prevents this
597 // from working.
598 template<typename Functor>
599   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
600   operator==(const function_base& f, Functor g)
601   {
602     if (const Functor* fp = f.template target<Functor>())
603       return function_equal(*fp, g);
604     else return false;
605   }
606
607 template<typename Functor>
608   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
609   operator==(Functor g, const function_base& f)
610   {
611     if (const Functor* fp = f.template target<Functor>())
612       return function_equal(g, *fp);
613     else return false;
614   }
615
616 template<typename Functor>
617   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
618   operator!=(const function_base& f, Functor g)
619   {
620     if (const Functor* fp = f.template target<Functor>())
621       return !function_equal(*fp, g);
622     else return true;
623   }
624
625 template<typename Functor>
626   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
627   operator!=(Functor g, const function_base& f)
628   {
629     if (const Functor* fp = f.template target<Functor>())
630       return !function_equal(g, *fp);
631     else return true;
632   }
633 #  endif
634
635 template<typename Functor>
636   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
637   operator==(const function_base& f, reference_wrapper<Functor> g)
638   {
639     if (const Functor* fp = f.template target<Functor>())
640       return fp == g.get_pointer();
641     else return false;
642   }
643
644 template<typename Functor>
645   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
646   operator==(reference_wrapper<Functor> g, const function_base& f)
647   {
648     if (const Functor* fp = f.template target<Functor>())
649       return g.get_pointer() == fp;
650     else return false;
651   }
652
653 template<typename Functor>
654   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
655   operator!=(const function_base& f, reference_wrapper<Functor> g)
656   {
657     if (const Functor* fp = f.template target<Functor>())
658       return fp != g.get_pointer();
659     else return true;
660   }
661
662 template<typename Functor>
663   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
664   operator!=(reference_wrapper<Functor> g, const function_base& f)
665   {
666     if (const Functor* fp = f.template target<Functor>())
667       return g.get_pointer() != fp;
668     else return true;
669   }
670
671 #endif // Compiler supporting SFINAE
672
673 namespace detail {
674   namespace function {
675     inline bool has_empty_target(const function_base* f)
676     {
677       return f->empty();
678     }
679
680 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
681     inline bool has_empty_target(const void*)
682     {
683       return false;
684     }
685 #else
686     inline bool has_empty_target(...)
687     {
688       return false;
689     }
690 #endif
691   } // end namespace function
692 } // end namespace detail
693 } // end namespace boost
694
695 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
696 #undef BOOST_FUNCTION_COMPARE_TYPE_ID
697
698 #endif // BOOST_FUNCTION_BASE_HEADER