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