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