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