1 // Boost.Function library
3 // Copyright Douglas Gregor 2001-2004. Use, modification and
4 // distribution is subject to the Boost Software License, Version
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // For more information, see http://www.boost.org
10 #ifndef BOOST_FUNCTION_BASE_HEADER
11 #define BOOST_FUNCTION_BASE_HEADER
18 #include <boost/config.hpp>
19 #include <boost/assert.hpp>
20 #include <boost/type_traits/is_integral.hpp>
21 #include <boost/type_traits/composite_traits.hpp>
22 #include <boost/type_traits/is_stateless.hpp>
23 #include <boost/ref.hpp>
24 #include <boost/pending/ct_if.hpp>
25 #include <boost/detail/workaround.hpp>
26 #ifndef BOOST_NO_SFINAE
27 # include "boost/utility/enable_if.hpp"
29 # include "boost/mpl/bool.hpp"
31 #include <boost/function_equal.hpp>
33 // Borrowed from Boost.Python library: determines the cases where we
34 // need to use std::type_info::name to compare instead of operator==.
35 # if (defined(__GNUC__) && __GNUC__ >= 3) \
37 || ( defined(__sgi) && defined(__host_mips))
39 # define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
40 (std::strcmp((X).name(),(Y).name()) == 0)
42 # define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
45 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
46 # define BOOST_FUNCTION_TARGET_FIX(x) x
48 # define BOOST_FUNCTION_TARGET_FIX(x)
51 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
52 // Work around a compiler bug.
53 // boost::python::objects::function has to be seen by the compiler before the
54 // boost::function class template.
55 namespace boost { namespace python { namespace objects {
60 #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
61 || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
62 || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
63 # define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
66 #define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
67 typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
68 (::boost::is_integral<Functor>::value)>::value), \
72 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
75 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
76 // The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
79 template<typename Signature,
80 typename Allocator = std::allocator<function_base> >
83 template<typename Signature, typename Allocator = std::allocator<void> >
87 template<typename Signature, typename Allocator>
88 inline void swap(function<Signature, Allocator>& f1,
89 function<Signature, Allocator>& f2)
94 } // end namespace boost
95 #endif // have partial specialization
101 * A union of a function pointer and a void pointer. This is necessary
102 * because 5.2.10/6 allows reinterpret_cast<> to safely cast between
103 * function pointer types and 5.2.9/10 allows static_cast<> to safely
104 * cast between a void pointer and an object pointer. But it is not legal
105 * to cast between a function pointer and a void* (in either direction),
106 * so function requires a union of the two. */
110 const void* const_obj_ptr;
115 inline any_pointer make_any_pointer(void* o)
122 inline any_pointer make_any_pointer(const void* o)
129 inline any_pointer make_any_pointer(void (*f)())
137 * The unusable class is a placeholder for unused function arguments
138 * It is also completely unusable except that it constructable from
139 * anything. This helps compilers without partial specialization to
140 * handle Boost.Function objects returning void.
145 template<typename T> unusable(const T&) {}
148 /* Determine the return type. This supports compilers that do not support
149 * void returns or partial specialization by silently changing the return
150 * type to "unusable".
152 template<typename T> struct function_return_type { typedef T type; };
155 struct function_return_type<void>
157 typedef unusable type;
160 // The operation type to perform on the given functor/function pointer
161 enum functor_manager_operation_type {
164 check_functor_type_tag
167 // Tags used to decide between different types of functions
168 struct function_ptr_tag {};
169 struct function_obj_tag {};
170 struct member_ptr_tag {};
171 struct function_obj_ref_tag {};
172 struct stateless_function_obj_tag {};
175 class get_function_tag
177 typedef typename ct_if<(is_pointer<F>::value),
179 function_obj_tag>::type ptr_or_obj_tag;
181 typedef typename ct_if<(is_member_pointer<F>::value),
183 ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
185 typedef typename ct_if<(is_reference_wrapper<F>::value),
186 function_obj_ref_tag,
187 ptr_or_obj_or_mem_tag>::type or_ref_tag;
190 typedef typename ct_if<(is_stateless<F>::value),
191 stateless_function_obj_tag,
192 or_ref_tag>::type type;
195 // The trivial manager does nothing but return the same pointer (if we
196 // are cloning) or return the null pointer (if we are deleting).
198 struct trivial_manager
200 static inline any_pointer
201 get(any_pointer f, functor_manager_operation_type op)
204 case clone_functor_tag: return f;
206 case destroy_functor_tag:
207 return make_any_pointer(reinterpret_cast<void*>(0));
209 case check_functor_type_tag:
211 std::type_info* t = static_cast<std::type_info*>(f.obj_ptr);
212 return BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(F), *t)?
214 : make_any_pointer(reinterpret_cast<void*>(0));
218 // Clears up a warning with GCC 3.2.3
219 return make_any_pointer(reinterpret_cast<void*>(0));
224 * The functor_manager class contains a static function "manage" which
225 * can clone or destroy the given function/function object pointer.
227 template<typename Functor, typename Allocator>
228 struct functor_manager
231 typedef Functor functor_type;
233 // For function pointers, the manager is trivial
234 static inline any_pointer
235 manager(any_pointer function_ptr,
236 functor_manager_operation_type op,
239 if (op == clone_functor_tag)
242 return make_any_pointer(static_cast<void (*)()>(0));
245 // For function object pointers, we clone the pointer to each
246 // function has its own version.
247 static inline any_pointer
248 manager(any_pointer function_obj_ptr,
249 functor_manager_operation_type op,
252 #ifndef BOOST_NO_STD_ALLOCATOR
253 typedef typename Allocator::template rebind<functor_type>::other
255 typedef typename allocator_type::pointer pointer_type;
257 typedef functor_type* pointer_type;
258 #endif // BOOST_NO_STD_ALLOCATOR
260 # ifndef BOOST_NO_STD_ALLOCATOR
261 allocator_type allocator;
262 # endif // BOOST_NO_STD_ALLOCATOR
264 if (op == clone_functor_tag) {
266 static_cast<functor_type*>(function_obj_ptr.obj_ptr);
269 # ifndef BOOST_NO_STD_ALLOCATOR
270 pointer_type copy = allocator.allocate(1);
271 allocator.construct(copy, *f);
273 // Get back to the original pointer type
274 functor_type* new_f = static_cast<functor_type*>(copy);
276 functor_type* new_f = new functor_type(*f);
277 # endif // BOOST_NO_STD_ALLOCATOR
278 return make_any_pointer(static_cast<void*>(new_f));
281 /* Cast from the void pointer to the functor pointer type */
283 reinterpret_cast<functor_type*>(function_obj_ptr.obj_ptr);
285 # ifndef BOOST_NO_STD_ALLOCATOR
286 /* Cast from the functor pointer type to the allocator's pointer
288 pointer_type victim = static_cast<pointer_type>(f);
290 // Destroy and deallocate the functor
291 allocator.destroy(victim);
292 allocator.deallocate(victim, 1);
295 # endif // BOOST_NO_STD_ALLOCATOR
297 return make_any_pointer(static_cast<void*>(0));
301 /* Dispatch to an appropriate manager based on whether we have a
302 function pointer or a function object pointer. */
304 manage(any_pointer functor_ptr, functor_manager_operation_type op)
306 if (op == check_functor_type_tag) {
307 std::type_info* type =
308 static_cast<std::type_info*>(functor_ptr.obj_ptr);
309 return (BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(Functor), *type)?
311 : make_any_pointer(reinterpret_cast<void*>(0)));
314 typedef typename get_function_tag<functor_type>::type tag_type;
315 return manager(functor_ptr, op, tag_type());
320 // A type that is only used for comparisons against zero
321 struct useless_clear_type {};
323 #ifdef BOOST_NO_SFINAE
324 // These routines perform comparisons between a Boost.Function
325 // object and an arbitrary function object (when the last
326 // parameter is mpl::bool_<false>) or against zero (when the
327 // last parameter is mpl::bool_<true>). They are only necessary
328 // for compilers that don't support SFINAE.
329 template<typename Function, typename Functor>
331 compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
332 { return f.empty(); }
334 template<typename Function, typename Functor>
336 compare_not_equal(const Function& f, const Functor&, int,
338 { return !f.empty(); }
340 template<typename Function, typename Functor>
342 compare_equal(const Function& f, const Functor& g, long,
345 if (const Functor* fp = f.template target<Functor>())
346 return function_equal(*fp, g);
350 template<typename Function, typename Functor>
352 compare_equal(const Function& f, const reference_wrapper<Functor>& g,
353 int, mpl::bool_<false>)
355 if (const Functor* fp = f.template target<Functor>())
356 return fp == g.get_pointer();
360 template<typename Function, typename Functor>
362 compare_not_equal(const Function& f, const Functor& g, long,
365 if (const Functor* fp = f.template target<Functor>())
366 return !function_equal(*fp, g);
370 template<typename Function, typename Functor>
372 compare_not_equal(const Function& f,
373 const reference_wrapper<Functor>& g, int,
376 if (const Functor* fp = f.template target<Functor>())
377 return fp != g.get_pointer();
380 #endif // BOOST_NO_SFINAE
381 } // end namespace function
382 } // end namespace detail
385 * The function_base class contains the basic elements needed for the
386 * function1, function2, function3, etc. classes. It is common to all
387 * functions (and as such can be used to tell if we have one of the
388 * functionN objects).
393 function_base() : manager(0)
398 // Is this function empty?
399 bool empty() const { return !manager; }
401 template<typename Functor>
404 if (!manager) return 0;
406 detail::function::any_pointer result =
407 manager(detail::function::make_any_pointer(&typeid(Functor)),
408 detail::function::check_functor_type_tag);
409 if (!result.obj_ptr) return 0;
411 typedef typename detail::function::get_function_tag<Functor>::type tag;
412 return get_functor_pointer<Functor>(tag(), 0);
416 template<typename Functor>
417 const Functor* target() const
419 if (!manager) return 0;
421 detail::function::any_pointer result =
422 manager(detail::function::make_any_pointer(&typeid(Functor)),
423 detail::function::check_functor_type_tag);
424 if (!result.obj_ptr) return 0;
426 typedef typename detail::function::get_function_tag<Functor>::type tag;
427 return get_functor_pointer<Functor>(tag(), 0);
432 bool contains(const F& f) const
434 if (const F* fp = this->template target<F>()) {
435 return function_equal(*fp, f);
441 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
442 // GCC 3.3 and newer cannot copy with the global operator==, due to
443 // problems with instantiation of function return types before it
444 // has been verified that the argument types match up.
445 template<typename Functor>
446 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
447 operator==(Functor g) const
449 if (const Functor* fp = target<Functor>())
450 return function_equal(*fp, g);
454 template<typename Functor>
455 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
456 operator!=(Functor g) const
458 if (const Functor* fp = target<Functor>())
459 return !function_equal(*fp, g);
464 public: // should be protected, but GCC 2.95.3 will fail to allow access
465 detail::function::any_pointer (*manager)(
466 detail::function::any_pointer,
467 detail::function::functor_manager_operation_type);
468 detail::function::any_pointer functor;
471 template<typename Functor>
472 Functor* get_functor_pointer(detail::function::function_ptr_tag, int)
473 { return reinterpret_cast<Functor*>(&functor.func_ptr); }
475 template<typename Functor, typename Tag>
476 Functor* get_functor_pointer(Tag, long)
477 { return static_cast<Functor*>(functor.obj_ptr); }
479 template<typename Functor>
481 get_functor_pointer(detail::function::function_ptr_tag, int) const
482 { return reinterpret_cast<const Functor*>(&functor.func_ptr); }
484 template<typename Functor, typename Tag>
485 const Functor* get_functor_pointer(Tag, long) const
486 { return static_cast<const Functor*>(functor.const_obj_ptr); }
490 * The bad_function_call exception class is thrown when a boost::function
493 class bad_function_call : public std::runtime_error
496 bad_function_call() : std::runtime_error("call to empty boost::function") {}
499 #ifndef BOOST_NO_SFINAE
500 inline bool operator==(const function_base& f,
501 detail::function::useless_clear_type*)
506 inline bool operator!=(const function_base& f,
507 detail::function::useless_clear_type*)
512 inline bool operator==(detail::function::useless_clear_type*,
513 const function_base& f)
518 inline bool operator!=(detail::function::useless_clear_type*,
519 const function_base& f)
525 #ifdef BOOST_NO_SFINAE
526 // Comparisons between boost::function objects and arbitrary function objects
527 template<typename Functor>
528 inline bool operator==(const function_base& f, Functor g)
530 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
531 return detail::function::compare_equal(f, g, 0, integral());
534 template<typename Functor>
535 inline bool operator==(Functor g, const function_base& f)
537 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
538 return detail::function::compare_equal(f, g, 0, integral());
541 template<typename Functor>
542 inline bool operator!=(const function_base& f, Functor g)
544 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
545 return detail::function::compare_not_equal(f, g, 0, integral());
548 template<typename Functor>
549 inline bool operator!=(Functor g, const function_base& f)
551 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
552 return detail::function::compare_not_equal(f, g, 0, integral());
556 # if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
557 // Comparisons between boost::function objects and arbitrary function
558 // objects. GCC 3.3 and before has an obnoxious bug that prevents this
560 template<typename Functor>
561 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
562 operator==(const function_base& f, Functor g)
564 if (const Functor* fp = f.template target<Functor>())
565 return function_equal(*fp, g);
569 template<typename Functor>
570 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
571 operator==(Functor g, const function_base& f)
573 if (const Functor* fp = f.template target<Functor>())
574 return function_equal(g, *fp);
578 template<typename Functor>
579 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
580 operator!=(const function_base& f, Functor g)
582 if (const Functor* fp = f.template target<Functor>())
583 return !function_equal(*fp, g);
587 template<typename Functor>
588 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
589 operator!=(Functor g, const function_base& f)
591 if (const Functor* fp = f.template target<Functor>())
592 return !function_equal(g, *fp);
597 template<typename Functor>
598 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
599 operator==(const function_base& f, reference_wrapper<Functor> g)
601 if (const Functor* fp = f.template target<Functor>())
602 return fp == g.get_pointer();
606 template<typename Functor>
607 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
608 operator==(reference_wrapper<Functor> g, const function_base& f)
610 if (const Functor* fp = f.template target<Functor>())
611 return g.get_pointer() == fp;
615 template<typename Functor>
616 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
617 operator!=(const function_base& f, reference_wrapper<Functor> g)
619 if (const Functor* fp = f.template target<Functor>())
620 return fp != g.get_pointer();
624 template<typename Functor>
625 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
626 operator!=(reference_wrapper<Functor> g, const function_base& f)
628 if (const Functor* fp = f.template target<Functor>())
629 return g.get_pointer() != fp;
633 #endif // Compiler supporting SFINAE
637 inline bool has_empty_target(const function_base* f)
642 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
643 inline bool has_empty_target(const void*)
648 inline bool has_empty_target(...)
653 } // end namespace function
654 } // end namespace detail
655 } // end namespace boost
657 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
658 #undef BOOST_FUNCTION_COMPARE_TYPE_ID
660 #endif // BOOST_FUNCTION_BASE_HEADER