]> AND Private Git Repository - canny.git/blob - stc/exp/ml_stc_linux_make_v1.0/include/boost/function/function_base.hpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
d528ea2148c7f786c05d2c91a47d267b66ebbfc6
[canny.git] / stc / exp / ml_stc_linux_make_v1.0 / include / boost / function / function_base.hpp
1 // Boost.Function library\r
2 \r
3 //  Copyright Douglas Gregor 2001-2006\r
4 //  Copyright Emil Dotchevski 2007\r
5 //  Use, modification and distribution is subject to the Boost Software License, Version 1.0.\r
6 //  (See accompanying file LICENSE_1_0.txt or copy at\r
7 //  http://www.boost.org/LICENSE_1_0.txt)\r
8 \r
9 // For more information, see http://www.boost.org\r
10 \r
11 #ifndef BOOST_FUNCTION_BASE_HEADER\r
12 #define BOOST_FUNCTION_BASE_HEADER\r
13 \r
14 #include <stdexcept>\r
15 #include <string>\r
16 #include <memory>\r
17 #include <new>\r
18 #include <boost/config.hpp>\r
19 #include <boost/detail/sp_typeinfo.hpp>\r
20 #include <boost/assert.hpp>\r
21 #include <boost/integer.hpp>\r
22 #include <boost/type_traits/has_trivial_copy.hpp>\r
23 #include <boost/type_traits/has_trivial_destructor.hpp>\r
24 #include <boost/type_traits/is_const.hpp>\r
25 #include <boost/type_traits/is_integral.hpp>\r
26 #include <boost/type_traits/is_volatile.hpp>\r
27 #include <boost/type_traits/composite_traits.hpp>\r
28 #include <boost/type_traits/ice.hpp>\r
29 #include <boost/ref.hpp>\r
30 #include <boost/mpl/if.hpp>\r
31 #include <boost/detail/workaround.hpp>\r
32 #include <boost/type_traits/alignment_of.hpp>\r
33 #ifndef BOOST_NO_SFINAE\r
34 #  include "boost/utility/enable_if.hpp"\r
35 #else\r
36 #  include "boost/mpl/bool.hpp"\r
37 #endif\r
38 #include <boost/function_equal.hpp>\r
39 #include <boost/function/function_fwd.hpp>\r
40 \r
41 #if defined(BOOST_MSVC)\r
42 #   pragma warning( push )\r
43 #   pragma warning( disable : 4793 ) // complaint about native code generation\r
44 #   pragma warning( disable : 4127 ) // "conditional expression is constant"\r
45 #endif       \r
46 \r
47 // Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.\r
48 #ifdef BOOST_NO_STD_TYPEINFO\r
49 // Embedded VC++ does not have type_info in namespace std\r
50 #  define BOOST_FUNCTION_STD_NS\r
51 #else\r
52 #  define BOOST_FUNCTION_STD_NS std\r
53 #endif\r
54 \r
55 // Borrowed from Boost.Python library: determines the cases where we\r
56 // need to use std::type_info::name to compare instead of operator==.\r
57 #if defined( BOOST_NO_TYPEID )\r
58 #  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))\r
59 #elif (defined(__GNUC__) && __GNUC__ >= 3) \\r
60  || defined(_AIX) \\r
61  || (   defined(__sgi) && defined(__host_mips))\r
62 #  include <cstring>\r
63 #  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \\r
64      (std::strcmp((X).name(),(Y).name()) == 0)\r
65 # else\r
66 #  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))\r
67 #endif\r
68 \r
69 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)\r
70 #  define BOOST_FUNCTION_TARGET_FIX(x) x\r
71 #else\r
72 #  define BOOST_FUNCTION_TARGET_FIX(x)\r
73 #endif // not MSVC\r
74 \r
75 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x5A0)\r
76 #  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)              \\r
77       typename ::boost::enable_if_c<(::boost::type_traits::ice_not<          \\r
78                             (::boost::is_integral<Functor>::value)>::value), \\r
79                            Type>::type\r
80 #else\r
81 // BCC doesn't recognize this depends on a template argument and complains\r
82 // about the use of 'typename'\r
83 #  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)     \\r
84       ::boost::enable_if_c<(::boost::type_traits::ice_not<          \\r
85                    (::boost::is_integral<Functor>::value)>::value), \\r
86                        Type>::type\r
87 #endif\r
88 \r
89 namespace boost {\r
90   namespace detail {\r
91     namespace function {\r
92       class X;\r
93 \r
94       /**\r
95        * A buffer used to store small function objects in\r
96        * boost::function. It is a union containing function pointers,\r
97        * object pointers, and a structure that resembles a bound\r
98        * member function pointer.\r
99        */\r
100       union function_buffer\r
101       {\r
102         // For pointers to function objects\r
103         mutable void* obj_ptr;\r
104 \r
105         // For pointers to std::type_info objects\r
106         struct type_t {\r
107           // (get_functor_type_tag, check_functor_type_tag).\r
108           const detail::sp_typeinfo* type;\r
109 \r
110           // Whether the type is const-qualified.\r
111           bool const_qualified;\r
112           // Whether the type is volatile-qualified.\r
113           bool volatile_qualified;\r
114         } type;\r
115 \r
116         // For function pointers of all kinds\r
117         mutable void (*func_ptr)();\r
118 \r
119         // For bound member pointers\r
120         struct bound_memfunc_ptr_t {\r
121           void (X::*memfunc_ptr)(int);\r
122           void* obj_ptr;\r
123         } bound_memfunc_ptr;\r
124 \r
125         // For references to function objects. We explicitly keep\r
126         // track of the cv-qualifiers on the object referenced.\r
127         struct obj_ref_t {\r
128           mutable void* obj_ptr;\r
129           bool is_const_qualified;\r
130           bool is_volatile_qualified;\r
131         } obj_ref;\r
132 \r
133         // To relax aliasing constraints\r
134         mutable char data;\r
135       };\r
136 \r
137       /**\r
138        * The unusable class is a placeholder for unused function arguments\r
139        * It is also completely unusable except that it constructable from\r
140        * anything. This helps compilers without partial specialization to\r
141        * handle Boost.Function objects returning void.\r
142        */\r
143       struct unusable\r
144       {\r
145         unusable() {}\r
146         template<typename T> unusable(const T&) {}\r
147       };\r
148 \r
149       /* Determine the return type. This supports compilers that do not support\r
150        * void returns or partial specialization by silently changing the return\r
151        * type to "unusable".\r
152        */\r
153       template<typename T> struct function_return_type { typedef T type; };\r
154 \r
155       template<>\r
156       struct function_return_type<void>\r
157       {\r
158         typedef unusable type;\r
159       };\r
160 \r
161       // The operation type to perform on the given functor/function pointer\r
162       enum functor_manager_operation_type {\r
163         clone_functor_tag,\r
164         move_functor_tag,\r
165         destroy_functor_tag,\r
166         check_functor_type_tag,\r
167         get_functor_type_tag\r
168       };\r
169 \r
170       // Tags used to decide between different types of functions\r
171       struct function_ptr_tag {};\r
172       struct function_obj_tag {};\r
173       struct member_ptr_tag {};\r
174       struct function_obj_ref_tag {};\r
175 \r
176       template<typename F>\r
177       class get_function_tag\r
178       {\r
179         typedef typename mpl::if_c<(is_pointer<F>::value),\r
180                                    function_ptr_tag,\r
181                                    function_obj_tag>::type ptr_or_obj_tag;\r
182 \r
183         typedef typename mpl::if_c<(is_member_pointer<F>::value),\r
184                                    member_ptr_tag,\r
185                                    ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;\r
186 \r
187         typedef typename mpl::if_c<(is_reference_wrapper<F>::value),\r
188                                    function_obj_ref_tag,\r
189                                    ptr_or_obj_or_mem_tag>::type or_ref_tag;\r
190 \r
191       public:\r
192         typedef or_ref_tag type;\r
193       };\r
194 \r
195       // The trivial manager does nothing but return the same pointer (if we\r
196       // are cloning) or return the null pointer (if we are deleting).\r
197       template<typename F>\r
198       struct reference_manager\r
199       {\r
200         static inline void\r
201         manage(const function_buffer& in_buffer, function_buffer& out_buffer, \r
202                functor_manager_operation_type op)\r
203         {\r
204           switch (op) {\r
205           case clone_functor_tag: \r
206             out_buffer.obj_ref.obj_ptr = in_buffer.obj_ref.obj_ptr;\r
207             return;\r
208 \r
209           case move_functor_tag:\r
210             out_buffer.obj_ref.obj_ptr = in_buffer.obj_ref.obj_ptr;\r
211             in_buffer.obj_ref.obj_ptr = 0;\r
212             return;\r
213 \r
214           case destroy_functor_tag:\r
215             out_buffer.obj_ref.obj_ptr = 0;\r
216             return;\r
217 \r
218           case check_functor_type_tag:\r
219             {\r
220               const detail::sp_typeinfo& check_type \r
221                 = *out_buffer.type.type;\r
222 \r
223               // Check whether we have the same type. We can add\r
224               // cv-qualifiers, but we can't take them away.\r
225               if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(F))\r
226                   && (!in_buffer.obj_ref.is_const_qualified \r
227                       || out_buffer.type.const_qualified)\r
228                   && (!in_buffer.obj_ref.is_volatile_qualified\r
229                       || out_buffer.type.volatile_qualified))\r
230                 out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;\r
231               else\r
232                 out_buffer.obj_ptr = 0;\r
233             }\r
234             return;\r
235 \r
236           case get_functor_type_tag:\r
237             out_buffer.type.type = &BOOST_SP_TYPEID(F);\r
238             out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;\r
239             out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;\r
240             return;\r
241           }\r
242         }\r
243       };\r
244 \r
245       /**\r
246        * Determine if boost::function can use the small-object\r
247        * optimization with the function object type F.\r
248        */\r
249       template<typename F>\r
250       struct function_allows_small_object_optimization\r
251       {\r
252         BOOST_STATIC_CONSTANT\r
253           (bool, \r
254            value = ((sizeof(F) <= sizeof(function_buffer) &&\r
255                      (alignment_of<function_buffer>::value \r
256                       % alignment_of<F>::value == 0))));\r
257       };\r
258 \r
259       template <typename F,typename A>\r
260       struct functor_wrapper: public F, public A\r
261       {\r
262         functor_wrapper( F f, A a ):\r
263           F(f),\r
264           A(a)\r
265         {\r
266         }\r
267         \r
268         functor_wrapper(const functor_wrapper& f) :\r
269           F(static_cast<const F&>(f)),\r
270           A(static_cast<const A&>(f))\r
271         {\r
272         }\r
273       };\r
274 \r
275       /**\r
276        * The functor_manager class contains a static function "manage" which\r
277        * can clone or destroy the given function/function object pointer.\r
278        */\r
279       template<typename Functor>\r
280       struct functor_manager_common\r
281       {\r
282         typedef Functor functor_type;\r
283 \r
284         // Function pointers\r
285         static inline void\r
286         manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer, \r
287                 functor_manager_operation_type op)\r
288         {\r
289           if (op == clone_functor_tag)\r
290             out_buffer.func_ptr = in_buffer.func_ptr;\r
291           else if (op == move_functor_tag) {\r
292             out_buffer.func_ptr = in_buffer.func_ptr;\r
293             in_buffer.func_ptr = 0;\r
294           } else if (op == destroy_functor_tag)\r
295             out_buffer.func_ptr = 0;\r
296           else if (op == check_functor_type_tag) {\r
297             const detail::sp_typeinfo& check_type \r
298               = *out_buffer.type.type;\r
299             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))\r
300               out_buffer.obj_ptr = &in_buffer.func_ptr;\r
301             else\r
302               out_buffer.obj_ptr = 0;\r
303           } else /* op == get_functor_type_tag */ {\r
304             out_buffer.type.type = &BOOST_SP_TYPEID(Functor);\r
305             out_buffer.type.const_qualified = false;\r
306             out_buffer.type.volatile_qualified = false;\r
307           }\r
308         }\r
309 \r
310         // Function objects that fit in the small-object buffer.\r
311         static inline void\r
312         manage_small(const function_buffer& in_buffer, function_buffer& out_buffer, \r
313                 functor_manager_operation_type op)\r
314         {\r
315           if (op == clone_functor_tag || op == move_functor_tag) {\r
316             const functor_type* in_functor = \r
317               reinterpret_cast<const functor_type*>(&in_buffer.data);\r
318             new ((void*)&out_buffer.data) functor_type(*in_functor);\r
319 \r
320             if (op == move_functor_tag) {\r
321               reinterpret_cast<functor_type*>(&in_buffer.data)->~Functor();\r
322             }\r
323           } else if (op == destroy_functor_tag) {\r
324             // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.\r
325             reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();\r
326           } else if (op == check_functor_type_tag) {\r
327             const detail::sp_typeinfo& check_type \r
328               = *out_buffer.type.type;\r
329             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))\r
330               out_buffer.obj_ptr = &in_buffer.data;\r
331             else\r
332               out_buffer.obj_ptr = 0;\r
333           } else /* op == get_functor_type_tag */ {\r
334             out_buffer.type.type = &BOOST_SP_TYPEID(Functor);\r
335             out_buffer.type.const_qualified = false;\r
336             out_buffer.type.volatile_qualified = false;            \r
337           }\r
338         }\r
339       };\r
340 \r
341       template<typename Functor>\r
342       struct functor_manager\r
343       {\r
344       private:\r
345         typedef Functor functor_type;\r
346 \r
347         // Function pointers\r
348         static inline void\r
349         manager(const function_buffer& in_buffer, function_buffer& out_buffer, \r
350                 functor_manager_operation_type op, function_ptr_tag)\r
351         {\r
352           functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);\r
353         }\r
354 \r
355         // Function objects that fit in the small-object buffer.\r
356         static inline void\r
357         manager(const function_buffer& in_buffer, function_buffer& out_buffer, \r
358                 functor_manager_operation_type op, mpl::true_)\r
359         {\r
360           functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);\r
361         }\r
362         \r
363         // Function objects that require heap allocation\r
364         static inline void\r
365         manager(const function_buffer& in_buffer, function_buffer& out_buffer, \r
366                 functor_manager_operation_type op, mpl::false_)\r
367         {\r
368           if (op == clone_functor_tag) {\r
369             // Clone the functor\r
370             // GCC 2.95.3 gets the CV qualifiers wrong here, so we\r
371             // can't do the static_cast that we should do.\r
372             const functor_type* f =\r
373               (const functor_type*)(in_buffer.obj_ptr);\r
374             functor_type* new_f = new functor_type(*f);\r
375             out_buffer.obj_ptr = new_f;\r
376           } else if (op == move_functor_tag) {\r
377             out_buffer.obj_ptr = in_buffer.obj_ptr;\r
378             in_buffer.obj_ptr = 0;\r
379           } else if (op == destroy_functor_tag) {\r
380             /* Cast from the void pointer to the functor pointer type */\r
381             functor_type* f =\r
382               static_cast<functor_type*>(out_buffer.obj_ptr);\r
383             delete f;\r
384             out_buffer.obj_ptr = 0;\r
385           } else if (op == check_functor_type_tag) {\r
386             const detail::sp_typeinfo& check_type\r
387               = *out_buffer.type.type;\r
388             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))\r
389               out_buffer.obj_ptr = in_buffer.obj_ptr;\r
390             else\r
391               out_buffer.obj_ptr = 0;\r
392           } else /* op == get_functor_type_tag */ {\r
393             out_buffer.type.type = &BOOST_SP_TYPEID(Functor);\r
394             out_buffer.type.const_qualified = false;\r
395             out_buffer.type.volatile_qualified = false;\r
396           }\r
397         }\r
398 \r
399         // For function objects, we determine whether the function\r
400         // object can use the small-object optimization buffer or\r
401         // whether we need to allocate it on the heap.\r
402         static inline void\r
403         manager(const function_buffer& in_buffer, function_buffer& out_buffer, \r
404                 functor_manager_operation_type op, function_obj_tag)\r
405         {\r
406           manager(in_buffer, out_buffer, op,\r
407                   mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());\r
408         }\r
409 \r
410         // For member pointers, we use the small-object optimization buffer.\r
411         static inline void\r
412         manager(const function_buffer& in_buffer, function_buffer& out_buffer, \r
413                 functor_manager_operation_type op, member_ptr_tag)\r
414         {\r
415           manager(in_buffer, out_buffer, op, mpl::true_());\r
416         }\r
417 \r
418       public:\r
419         /* Dispatch to an appropriate manager based on whether we have a\r
420            function pointer or a function object pointer. */\r
421         static inline void\r
422         manage(const function_buffer& in_buffer, function_buffer& out_buffer, \r
423                functor_manager_operation_type op)\r
424         {\r
425           typedef typename get_function_tag<functor_type>::type tag_type;\r
426           switch (op) {\r
427           case get_functor_type_tag:\r
428             out_buffer.type.type = &BOOST_SP_TYPEID(functor_type);\r
429             out_buffer.type.const_qualified = false;\r
430             out_buffer.type.volatile_qualified = false;\r
431             return;\r
432 \r
433           default:\r
434             manager(in_buffer, out_buffer, op, tag_type());\r
435             return;\r
436           }\r
437         }\r
438       };\r
439 \r
440       template<typename Functor, typename Allocator>\r
441       struct functor_manager_a\r
442       {\r
443       private:\r
444         typedef Functor functor_type;\r
445 \r
446         // Function pointers\r
447         static inline void\r
448         manager(const function_buffer& in_buffer, function_buffer& out_buffer, \r
449                 functor_manager_operation_type op, function_ptr_tag)\r
450         {\r
451           functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);\r
452         }\r
453 \r
454         // Function objects that fit in the small-object buffer.\r
455         static inline void\r
456         manager(const function_buffer& in_buffer, function_buffer& out_buffer, \r
457                 functor_manager_operation_type op, mpl::true_)\r
458         {\r
459           functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);\r
460         }\r
461         \r
462         // Function objects that require heap allocation\r
463         static inline void\r
464         manager(const function_buffer& in_buffer, function_buffer& out_buffer, \r
465                 functor_manager_operation_type op, mpl::false_)\r
466         {\r
467           typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;\r
468           typedef typename Allocator::template rebind<functor_wrapper_type>::other\r
469             wrapper_allocator_type;\r
470           typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;\r
471 \r
472           if (op == clone_functor_tag) {\r
473             // Clone the functor\r
474             // GCC 2.95.3 gets the CV qualifiers wrong here, so we\r
475             // can't do the static_cast that we should do.\r
476             const functor_wrapper_type* f =\r
477               (const functor_wrapper_type*)(in_buffer.obj_ptr);\r
478             wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));\r
479             wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);\r
480             wrapper_allocator.construct(copy, *f);\r
481 \r
482             // Get back to the original pointer type\r
483             functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);\r
484             out_buffer.obj_ptr = new_f;\r
485           } else if (op == move_functor_tag) {\r
486             out_buffer.obj_ptr = in_buffer.obj_ptr;\r
487             in_buffer.obj_ptr = 0;\r
488           } else if (op == destroy_functor_tag) {\r
489             /* Cast from the void pointer to the functor_wrapper_type */\r
490             functor_wrapper_type* victim =\r
491               static_cast<functor_wrapper_type*>(in_buffer.obj_ptr);\r
492             wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));\r
493             wrapper_allocator.destroy(victim);\r
494             wrapper_allocator.deallocate(victim,1);\r
495             out_buffer.obj_ptr = 0;\r
496           } else if (op == check_functor_type_tag) {\r
497             const detail::sp_typeinfo& check_type \r
498               = *out_buffer.type.type;\r
499             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))\r
500               out_buffer.obj_ptr = in_buffer.obj_ptr;\r
501             else\r
502               out_buffer.obj_ptr = 0;\r
503           } else /* op == get_functor_type_tag */ {\r
504             out_buffer.type.type = &BOOST_SP_TYPEID(Functor);\r
505             out_buffer.type.const_qualified = false;\r
506             out_buffer.type.volatile_qualified = false;\r
507           }\r
508         }\r
509 \r
510         // For function objects, we determine whether the function\r
511         // object can use the small-object optimization buffer or\r
512         // whether we need to allocate it on the heap.\r
513         static inline void\r
514         manager(const function_buffer& in_buffer, function_buffer& out_buffer, \r
515                 functor_manager_operation_type op, function_obj_tag)\r
516         {\r
517           manager(in_buffer, out_buffer, op,\r
518                   mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());\r
519         }\r
520 \r
521       public:\r
522         /* Dispatch to an appropriate manager based on whether we have a\r
523            function pointer or a function object pointer. */\r
524         static inline void\r
525         manage(const function_buffer& in_buffer, function_buffer& out_buffer, \r
526                functor_manager_operation_type op)\r
527         {\r
528           typedef typename get_function_tag<functor_type>::type tag_type;\r
529           switch (op) {\r
530           case get_functor_type_tag:\r
531             out_buffer.type.type = &BOOST_SP_TYPEID(functor_type);\r
532             out_buffer.type.const_qualified = false;\r
533             out_buffer.type.volatile_qualified = false;\r
534             return;\r
535 \r
536           default:\r
537             manager(in_buffer, out_buffer, op, tag_type());\r
538             return;\r
539           }\r
540         }\r
541       };\r
542 \r
543       // A type that is only used for comparisons against zero\r
544       struct useless_clear_type {};\r
545 \r
546 #ifdef BOOST_NO_SFINAE\r
547       // These routines perform comparisons between a Boost.Function\r
548       // object and an arbitrary function object (when the last\r
549       // parameter is mpl::bool_<false>) or against zero (when the\r
550       // last parameter is mpl::bool_<true>). They are only necessary\r
551       // for compilers that don't support SFINAE.\r
552       template<typename Function, typename Functor>\r
553         bool\r
554         compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)\r
555         { return f.empty(); }\r
556 \r
557       template<typename Function, typename Functor>\r
558         bool\r
559         compare_not_equal(const Function& f, const Functor&, int,\r
560                           mpl::bool_<true>)\r
561         { return !f.empty(); }\r
562 \r
563       template<typename Function, typename Functor>\r
564         bool\r
565         compare_equal(const Function& f, const Functor& g, long,\r
566                       mpl::bool_<false>)\r
567         {\r
568           if (const Functor* fp = f.template target<Functor>())\r
569             return function_equal(*fp, g);\r
570           else return false;\r
571         }\r
572 \r
573       template<typename Function, typename Functor>\r
574         bool\r
575         compare_equal(const Function& f, const reference_wrapper<Functor>& g,\r
576                       int, mpl::bool_<false>)\r
577         {\r
578           if (const Functor* fp = f.template target<Functor>())\r
579             return fp == g.get_pointer();\r
580           else return false;\r
581         }\r
582 \r
583       template<typename Function, typename Functor>\r
584         bool\r
585         compare_not_equal(const Function& f, const Functor& g, long,\r
586                           mpl::bool_<false>)\r
587         {\r
588           if (const Functor* fp = f.template target<Functor>())\r
589             return !function_equal(*fp, g);\r
590           else return true;\r
591         }\r
592 \r
593       template<typename Function, typename Functor>\r
594         bool\r
595         compare_not_equal(const Function& f,\r
596                           const reference_wrapper<Functor>& g, int,\r
597                           mpl::bool_<false>)\r
598         {\r
599           if (const Functor* fp = f.template target<Functor>())\r
600             return fp != g.get_pointer();\r
601           else return true;\r
602         }\r
603 #endif // BOOST_NO_SFINAE\r
604 \r
605       /**\r
606        * Stores the "manager" portion of the vtable for a\r
607        * boost::function object.\r
608        */\r
609       struct vtable_base\r
610       {\r
611         void (*manager)(const function_buffer& in_buffer, \r
612                         function_buffer& out_buffer, \r
613                         functor_manager_operation_type op);\r
614       };\r
615     } // end namespace function\r
616   } // end namespace detail\r
617 \r
618 /**\r
619  * The function_base class contains the basic elements needed for the\r
620  * function1, function2, function3, etc. classes. It is common to all\r
621  * functions (and as such can be used to tell if we have one of the\r
622  * functionN objects).\r
623  */\r
624 class function_base\r
625 {\r
626 public:\r
627   function_base() : vtable(0) { }\r
628 \r
629   /** Determine if the function is empty (i.e., has no target). */\r
630   bool empty() const { return !vtable; }\r
631 \r
632   /** Retrieve the type of the stored function object, or BOOST_SP_TYPEID(void)\r
633       if this is empty. */\r
634   const detail::sp_typeinfo& target_type() const\r
635   {\r
636     if (!vtable) return BOOST_SP_TYPEID(void);\r
637 \r
638     detail::function::function_buffer type;\r
639     get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);\r
640     return *type.type.type;\r
641   }\r
642 \r
643   template<typename Functor>\r
644     Functor* target()\r
645     {\r
646       if (!vtable) return 0;\r
647 \r
648       detail::function::function_buffer type_result;\r
649       type_result.type.type = &BOOST_SP_TYPEID(Functor);\r
650       type_result.type.const_qualified = is_const<Functor>::value;\r
651       type_result.type.volatile_qualified = is_volatile<Functor>::value;\r
652       get_vtable()->manager(functor, type_result, \r
653                       detail::function::check_functor_type_tag);\r
654       return static_cast<Functor*>(type_result.obj_ptr);\r
655     }\r
656 \r
657   template<typename Functor>\r
658 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)\r
659     const Functor* target( Functor * = 0 ) const\r
660 #else\r
661     const Functor* target() const\r
662 #endif\r
663     {\r
664       if (!vtable) return 0;\r
665 \r
666       detail::function::function_buffer type_result;\r
667       type_result.type.type = &BOOST_SP_TYPEID(Functor);\r
668       type_result.type.const_qualified = true;\r
669       type_result.type.volatile_qualified = is_volatile<Functor>::value;\r
670       get_vtable()->manager(functor, type_result, \r
671                       detail::function::check_functor_type_tag);\r
672       // GCC 2.95.3 gets the CV qualifiers wrong here, so we\r
673       // can't do the static_cast that we should do.\r
674       return (const Functor*)(type_result.obj_ptr);\r
675     }\r
676 \r
677   template<typename F>\r
678     bool contains(const F& f) const\r
679     {\r
680 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)\r
681       if (const F* fp = this->target( (F*)0 ))\r
682 #else\r
683       if (const F* fp = this->template target<F>())\r
684 #endif\r
685       {\r
686         return function_equal(*fp, f);\r
687       } else {\r
688         return false;\r
689       }\r
690     }\r
691 \r
692 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3\r
693   // GCC 3.3 and newer cannot copy with the global operator==, due to\r
694   // problems with instantiation of function return types before it\r
695   // has been verified that the argument types match up.\r
696   template<typename Functor>\r
697     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)\r
698     operator==(Functor g) const\r
699     {\r
700       if (const Functor* fp = target<Functor>())\r
701         return function_equal(*fp, g);\r
702       else return false;\r
703     }\r
704 \r
705   template<typename Functor>\r
706     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)\r
707     operator!=(Functor g) const\r
708     {\r
709       if (const Functor* fp = target<Functor>())\r
710         return !function_equal(*fp, g);\r
711       else return true;\r
712     }\r
713 #endif\r
714 \r
715 public: // should be protected, but GCC 2.95.3 will fail to allow access\r
716   detail::function::vtable_base* get_vtable() const {\r
717     return reinterpret_cast<detail::function::vtable_base*>(\r
718              reinterpret_cast<std::size_t>(vtable) & ~(std::size_t)0x01);\r
719   }\r
720 \r
721   bool has_trivial_copy_and_destroy() const {\r
722     return reinterpret_cast<std::size_t>(vtable) & 0x01;\r
723   }\r
724 \r
725   detail::function::vtable_base* vtable;\r
726   mutable detail::function::function_buffer functor;\r
727 };\r
728 \r
729 /**\r
730  * The bad_function_call exception class is thrown when a boost::function\r
731  * object is invoked\r
732  */\r
733 class bad_function_call : public std::runtime_error\r
734 {\r
735 public:\r
736   bad_function_call() : std::runtime_error("call to empty boost::function") {}\r
737 };\r
738 \r
739 #ifndef BOOST_NO_SFINAE\r
740 inline bool operator==(const function_base& f,\r
741                        detail::function::useless_clear_type*)\r
742 {\r
743   return f.empty();\r
744 }\r
745 \r
746 inline bool operator!=(const function_base& f,\r
747                        detail::function::useless_clear_type*)\r
748 {\r
749   return !f.empty();\r
750 }\r
751 \r
752 inline bool operator==(detail::function::useless_clear_type*,\r
753                        const function_base& f)\r
754 {\r
755   return f.empty();\r
756 }\r
757 \r
758 inline bool operator!=(detail::function::useless_clear_type*,\r
759                        const function_base& f)\r
760 {\r
761   return !f.empty();\r
762 }\r
763 #endif\r
764 \r
765 #ifdef BOOST_NO_SFINAE\r
766 // Comparisons between boost::function objects and arbitrary function objects\r
767 template<typename Functor>\r
768   inline bool operator==(const function_base& f, Functor g)\r
769   {\r
770     typedef mpl::bool_<(is_integral<Functor>::value)> integral;\r
771     return detail::function::compare_equal(f, g, 0, integral());\r
772   }\r
773 \r
774 template<typename Functor>\r
775   inline bool operator==(Functor g, const function_base& f)\r
776   {\r
777     typedef mpl::bool_<(is_integral<Functor>::value)> integral;\r
778     return detail::function::compare_equal(f, g, 0, integral());\r
779   }\r
780 \r
781 template<typename Functor>\r
782   inline bool operator!=(const function_base& f, Functor g)\r
783   {\r
784     typedef mpl::bool_<(is_integral<Functor>::value)> integral;\r
785     return detail::function::compare_not_equal(f, g, 0, integral());\r
786   }\r
787 \r
788 template<typename Functor>\r
789   inline bool operator!=(Functor g, const function_base& f)\r
790   {\r
791     typedef mpl::bool_<(is_integral<Functor>::value)> integral;\r
792     return detail::function::compare_not_equal(f, g, 0, integral());\r
793   }\r
794 #else\r
795 \r
796 #  if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)\r
797 // Comparisons between boost::function objects and arbitrary function\r
798 // objects. GCC 3.3 and before has an obnoxious bug that prevents this\r
799 // from working.\r
800 template<typename Functor>\r
801   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)\r
802   operator==(const function_base& f, Functor g)\r
803   {\r
804     if (const Functor* fp = f.template target<Functor>())\r
805       return function_equal(*fp, g);\r
806     else return false;\r
807   }\r
808 \r
809 template<typename Functor>\r
810   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)\r
811   operator==(Functor g, const function_base& f)\r
812   {\r
813     if (const Functor* fp = f.template target<Functor>())\r
814       return function_equal(g, *fp);\r
815     else return false;\r
816   }\r
817 \r
818 template<typename Functor>\r
819   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)\r
820   operator!=(const function_base& f, Functor g)\r
821   {\r
822     if (const Functor* fp = f.template target<Functor>())\r
823       return !function_equal(*fp, g);\r
824     else return true;\r
825   }\r
826 \r
827 template<typename Functor>\r
828   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)\r
829   operator!=(Functor g, const function_base& f)\r
830   {\r
831     if (const Functor* fp = f.template target<Functor>())\r
832       return !function_equal(g, *fp);\r
833     else return true;\r
834   }\r
835 #  endif\r
836 \r
837 template<typename Functor>\r
838   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)\r
839   operator==(const function_base& f, reference_wrapper<Functor> g)\r
840   {\r
841     if (const Functor* fp = f.template target<Functor>())\r
842       return fp == g.get_pointer();\r
843     else return false;\r
844   }\r
845 \r
846 template<typename Functor>\r
847   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)\r
848   operator==(reference_wrapper<Functor> g, const function_base& f)\r
849   {\r
850     if (const Functor* fp = f.template target<Functor>())\r
851       return g.get_pointer() == fp;\r
852     else return false;\r
853   }\r
854 \r
855 template<typename Functor>\r
856   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)\r
857   operator!=(const function_base& f, reference_wrapper<Functor> g)\r
858   {\r
859     if (const Functor* fp = f.template target<Functor>())\r
860       return fp != g.get_pointer();\r
861     else return true;\r
862   }\r
863 \r
864 template<typename Functor>\r
865   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)\r
866   operator!=(reference_wrapper<Functor> g, const function_base& f)\r
867   {\r
868     if (const Functor* fp = f.template target<Functor>())\r
869       return g.get_pointer() != fp;\r
870     else return true;\r
871   }\r
872 \r
873 #endif // Compiler supporting SFINAE\r
874 \r
875 namespace detail {\r
876   namespace function {\r
877     inline bool has_empty_target(const function_base* f)\r
878     {\r
879       return f->empty();\r
880     }\r
881 \r
882 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)\r
883     inline bool has_empty_target(const void*)\r
884     {\r
885       return false;\r
886     }\r
887 #else\r
888     inline bool has_empty_target(...)\r
889     {\r
890       return false;\r
891     }\r
892 #endif\r
893   } // end namespace function\r
894 } // end namespace detail\r
895 } // end namespace boost\r
896 \r
897 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL\r
898 #undef BOOST_FUNCTION_COMPARE_TYPE_ID\r
899 \r
900 #if defined(BOOST_MSVC)\r
901 #   pragma warning( pop )\r
902 #endif       \r
903 \r
904 #endif // BOOST_FUNCTION_BASE_HEADER\r