]> git.lyx.org Git - lyx.git/blob - boost/boost/function/function_base.hpp
update boost to pre-1.30.0
[lyx.git] / boost / boost / function / function_base.hpp
1 // Boost.Function library
2
3 // Copyright (C) 2001-2003 Doug Gregor (gregod@cs.rpi.edu)
4 //
5 // Permission to copy, use, sell and distribute this software is granted
6 // provided this copyright notice appears in all copies.
7 // Permission to modify the code and to distribute modified code is granted
8 // provided this copyright notice appears in all copies, and a notice
9 // that the code was modified is included with the copyright notice.
10 //
11 // This software is provided "as is" without express or implied warranty,
12 // and with no claim as to its suitability for any purpose.
13
14 // For more information, see http://www.boost.org
15
16 #ifndef BOOST_FUNCTION_BASE_HEADER
17 #define BOOST_FUNCTION_BASE_HEADER
18
19 #include <stdexcept>
20 #include <string>
21 #include <memory>
22 #include <new>
23 #include <boost/config.hpp>
24 #include <boost/assert.hpp>
25 #include <boost/type_traits/arithmetic_traits.hpp>
26 #include <boost/type_traits/composite_traits.hpp>
27 #include <boost/type_traits/is_stateless.hpp>
28 #include <boost/ref.hpp>
29 #include <boost/pending/ct_if.hpp>
30 #include <boost/detail/workaround.hpp>
31
32 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
33 #  define BOOST_FUNCTION_TARGET_FIX(x) x
34 #else
35 #  define BOOST_FUNCTION_TARGET_FIX(x)
36 #endif // not MSVC
37
38 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
39 // Work around a compiler bug.
40 // boost::python::objects::function has to be seen by the compiler before the
41 // boost::function class template.
42 namespace boost { namespace python { namespace objects {
43   class function;
44 }}}
45 #endif
46
47 // GCC 2.95.3 (or earlier) doesn't support enable_if
48 #if BOOST_WORKAROUND(__GNUC__, < 3)
49 #  define BOOST_FUNCTION_NO_ENABLE_IF
50 #endif
51
52 // MIPSpro 7.3.1.3m doesn't support enable_if
53 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
54 #  define BOOST_FUNCTION_NO_ENABLE_IF
55 #endif
56
57 // MSVC 7.0 doesn't support enable_if
58 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && !defined(BOOST_STRICT_CONFIG)
59 #  define BOOST_FUNCTION_NO_ENABLE_IF
60 #endif
61
62 // Borland C++ 5.6.0 doesn't support enable_if
63 #if BOOST_WORKAROUND(__BORLANDC__, <= 0x562)
64 #  define BOOST_FUNCTION_NO_ENABLE_IF
65 #endif
66
67 // Metrowerks 7.2 doesn't support enable_if
68 #if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
69 #  define BOOST_FUNCTION_NO_ENABLE_IF
70 #endif
71
72 #if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x540)
73 #  define BOOST_FUNCTION_NO_ENABLE_IF
74 #endif
75
76 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
77 namespace boost {
78
79 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
80 // The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
81 class function_base;
82
83 template<typename Signature,
84          typename Allocator = std::allocator<function_base> >
85 class function;
86 #else
87 template<typename Signature, typename Allocator = std::allocator<void> >
88 class function;
89 #endif
90
91 template<typename Signature, typename Allocator>
92 inline void swap(function<Signature, Allocator>& f1,
93                  function<Signature, Allocator>& f2)
94 {
95   f1.swap(f2);
96 }
97
98 } // end namespace boost
99 #endif // have partial specialization
100
101 namespace boost {
102   namespace detail {
103     namespace function {
104       /**
105        * A union of a function pointer and a void pointer. This is necessary
106        * because 5.2.10/6 allows reinterpret_cast<> to safely cast between
107        * function pointer types and 5.2.9/10 allows static_cast<> to safely
108        * cast between a void pointer and an object pointer. But it is not legal
109        * to cast between a function pointer and a void* (in either direction),
110        * so function requires a union of the two. */
111       union any_pointer
112       {
113         void* obj_ptr;
114         const void* const_obj_ptr;
115         void (*func_ptr)();
116         char data[1];
117       };
118
119       inline any_pointer make_any_pointer(void* o)
120       {
121         any_pointer p;
122         p.obj_ptr = o;
123         return p;
124       }
125
126       inline any_pointer make_any_pointer(const void* o)
127       {
128         any_pointer p;
129         p.const_obj_ptr = o;
130         return p;
131       }
132
133       inline any_pointer make_any_pointer(void (*f)())
134       {
135         any_pointer p;
136         p.func_ptr = f;
137         return p;
138       }
139
140       /**
141        * The unusable class is a placeholder for unused function arguments
142        * It is also completely unusable except that it constructable from
143        * anything. This helps compilers without partial specialization to
144        * handle Boost.Function objects returning void.
145        */
146       struct unusable
147       {
148         unusable() {}
149         template<typename T> unusable(const T&) {}
150       };
151
152       /* Determine the return type. This supports compilers that do not support
153        * void returns or partial specialization by silently changing the return
154        * type to "unusable".
155        */
156       template<typename T> struct function_return_type { typedef T type; };
157
158       template<>
159       struct function_return_type<void>
160       {
161         typedef unusable type;
162       };
163
164       // The operation type to perform on the given functor/function pointer
165       enum functor_manager_operation_type {
166         clone_functor_tag,
167         destroy_functor_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       struct stateless_function_obj_tag {};
176
177       template<typename F>
178       class get_function_tag
179       {
180         typedef typename ct_if<(is_pointer<F>::value),
181                             function_ptr_tag,
182                             function_obj_tag>::type ptr_or_obj_tag;
183
184         typedef typename ct_if<(is_member_pointer<F>::value),
185                             member_ptr_tag,
186                             ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
187
188         typedef typename ct_if<(is_reference_wrapper<F>::value),
189                              function_obj_ref_tag,
190                              ptr_or_obj_or_mem_tag>::type or_ref_tag;
191
192       public:
193         typedef typename ct_if<(is_stateless<F>::value),
194                             stateless_function_obj_tag,
195                             or_ref_tag>::type type;
196       };
197
198       // The trivial manager does nothing but return the same pointer (if we
199       // are cloning) or return the null pointer (if we are deleting).
200       inline any_pointer trivial_manager(any_pointer f,
201                                          functor_manager_operation_type op)
202       {
203         if (op == clone_functor_tag)
204           return f;
205         else
206           return make_any_pointer(reinterpret_cast<void*>(0));
207       }
208
209       /**
210        * The functor_manager class contains a static function "manage" which
211        * can clone or destroy the given function/function object pointer.
212        */
213       template<typename Functor, typename Allocator>
214       struct functor_manager
215       {
216       private:
217         typedef Functor functor_type;
218
219         // For function pointers, the manager is trivial
220         static inline any_pointer
221         manager(any_pointer function_ptr,
222                 functor_manager_operation_type op,
223                 function_ptr_tag)
224         {
225           if (op == clone_functor_tag)
226             return function_ptr;
227           else
228             return make_any_pointer(static_cast<void (*)()>(0));
229         }
230
231         // For function object pointers, we clone the pointer to each
232         // function has its own version.
233         static inline any_pointer
234         manager(any_pointer function_obj_ptr,
235                 functor_manager_operation_type op,
236                 function_obj_tag)
237         {
238 #ifndef BOOST_NO_STD_ALLOCATOR
239         typedef typename Allocator::template rebind<functor_type>::other
240           allocator_type;
241         typedef typename allocator_type::pointer pointer_type;
242 #else
243         typedef functor_type* pointer_type;
244 #endif // BOOST_NO_STD_ALLOCATOR
245
246 #  ifndef BOOST_NO_STD_ALLOCATOR
247           allocator_type allocator;
248 #  endif // BOOST_NO_STD_ALLOCATOR
249
250           if (op == clone_functor_tag) {
251             functor_type* f =
252               static_cast<functor_type*>(function_obj_ptr.obj_ptr);
253
254             // Clone the functor
255 #  ifndef BOOST_NO_STD_ALLOCATOR
256             pointer_type copy = allocator.allocate(1);
257             allocator.construct(copy, *f);
258
259             // Get back to the original pointer type
260             functor_type* new_f = static_cast<functor_type*>(copy);
261 #  else
262             functor_type* new_f = new functor_type(*f);
263 #  endif // BOOST_NO_STD_ALLOCATOR
264             return make_any_pointer(static_cast<void*>(new_f));
265           }
266           else {
267             /* Cast from the void pointer to the functor pointer type */
268             functor_type* f =
269               reinterpret_cast<functor_type*>(function_obj_ptr.obj_ptr);
270
271 #  ifndef BOOST_NO_STD_ALLOCATOR
272             /* Cast from the functor pointer type to the allocator's pointer
273                type */
274             pointer_type victim = static_cast<pointer_type>(f);
275
276             // Destroy and deallocate the functor
277             allocator.destroy(victim);
278             allocator.deallocate(victim, 1);
279 #  else
280             delete f;
281 #  endif // BOOST_NO_STD_ALLOCATOR
282
283             return make_any_pointer(static_cast<void*>(0));
284           }
285         }
286       public:
287         /* Dispatch to an appropriate manager based on whether we have a
288            function pointer or a function object pointer. */
289         static any_pointer
290         manage(any_pointer functor_ptr, functor_manager_operation_type op)
291         {
292           typedef typename get_function_tag<functor_type>::type tag_type;
293           return manager(functor_ptr, op, tag_type());
294         }
295       };
296
297 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
298     template<bool cond, typename T> struct enable_if;
299     template<typename T> struct enable_if<true, T>  { typedef T type; };
300     template<typename T> struct enable_if<false, T> {};
301
302     template<bool x>
303     struct enabled
304     {
305       template<typename T>
306       struct base
307       {
308         typedef T type;
309       };
310     };
311
312     template<>
313     struct enabled<false>
314     {
315       template<typename T>
316       struct base
317       {
318       };
319     };
320
321     template<bool Enabled, typename T>
322     struct enable_if : public enabled<Enabled>::template base<T>
323     {
324     };
325 #endif
326
327       // A type that is only used for comparisons against zero
328       struct useless_clear_type {};
329     } // end namespace function
330   } // end namespace detail
331
332 /**
333  * The function_base class contains the basic elements needed for the
334  * function1, function2, function3, etc. classes. It is common to all
335  * functions (and as such can be used to tell if we have one of the
336  * functionN objects).
337  */
338 class function_base
339 {
340 public:
341   function_base() : manager(0)
342   {
343     functor.obj_ptr = 0;
344   }
345
346   // Is this function empty?
347   bool empty() const { return !manager; }
348
349 public: // should be protected, but GCC 2.95.3 will fail to allow access
350   detail::function::any_pointer (*manager)(
351     detail::function::any_pointer,
352     detail::function::functor_manager_operation_type);
353   detail::function::any_pointer functor;
354 };
355
356 /**
357  * The bad_function_call exception class is thrown when a boost::function
358  * object is invoked
359  */
360 class bad_function_call : public std::runtime_error
361 {
362 public:
363   bad_function_call() : std::runtime_error("call to empty boost::function") {}
364 };
365
366 /* Poison comparison between Boost.Function objects (because it is
367  * meaningless). The comparisons would otherwise be allowed because of the
368  * conversion required to allow syntax such as:
369  *   boost::function<int, int> f;
370  *   if (f) { f(5); }
371  */
372 void operator==(const function_base&, const function_base&);
373 void operator!=(const function_base&, const function_base&);
374
375 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
376 inline bool operator==(const function_base& f,
377                        detail::function::useless_clear_type*)
378 {
379   return f.empty();
380 }
381
382 inline bool operator!=(const function_base& f,
383                        detail::function::useless_clear_type*)
384 {
385   return !f.empty();
386 }
387
388 inline bool operator==(detail::function::useless_clear_type*,
389                        const function_base& f)
390 {
391   return f.empty();
392 }
393
394 inline bool operator!=(detail::function::useless_clear_type*,
395                        const function_base& f)
396 {
397   return !f.empty();
398 }
399 #endif
400
401 namespace detail {
402   namespace function {
403     inline bool has_empty_target(const function_base* f)
404     {
405       return f->empty();
406     }
407
408     inline bool has_empty_target(...)
409     {
410       return false;
411     }
412   } // end namespace function
413 } // end namespace detail
414 } // end namespace boost
415
416 #endif // BOOST_FUNCTION_BASE_HEADER