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