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 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x600)
67 # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
68 typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
69 (::boost::is_integral<Functor>::value)>::value), \
72 // BCC doesn't recognize this depends on a template argument and complains
73 // about the use of 'typename'
74 # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
75 ::boost::enable_if_c<(::boost::type_traits::ice_not< \
76 (::boost::is_integral<Functor>::value)>::value), \
80 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
83 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
84 // The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
87 template<typename Signature,
88 typename Allocator = std::allocator<function_base> >
91 template<typename Signature, typename Allocator = std::allocator<void> >
95 template<typename Signature, typename Allocator>
96 inline void swap(function<Signature, Allocator>& f1,
97 function<Signature, Allocator>& f2)
102 } // end namespace boost
103 #endif // have partial specialization
109 * A union of a function pointer and a void pointer. This is necessary
110 * because 5.2.10/6 allows reinterpret_cast<> to safely cast between
111 * function pointer types and 5.2.9/10 allows static_cast<> to safely
112 * cast between a void pointer and an object pointer. But it is not legal
113 * to cast between a function pointer and a void* (in either direction),
114 * so function requires a union of the two. */
118 const void* const_obj_ptr;
123 inline any_pointer make_any_pointer(void* o)
130 inline any_pointer make_any_pointer(const void* o)
137 inline any_pointer make_any_pointer(void (*f)())
145 * The unusable class is a placeholder for unused function arguments
146 * It is also completely unusable except that it constructable from
147 * anything. This helps compilers without partial specialization to
148 * handle Boost.Function objects returning void.
153 template<typename T> unusable(const T&) {}
156 /* Determine the return type. This supports compilers that do not support
157 * void returns or partial specialization by silently changing the return
158 * type to "unusable".
160 template<typename T> struct function_return_type { typedef T type; };
163 struct function_return_type<void>
165 typedef unusable type;
168 // The operation type to perform on the given functor/function pointer
169 enum functor_manager_operation_type {
172 check_functor_type_tag
175 // Tags used to decide between different types of functions
176 struct function_ptr_tag {};
177 struct function_obj_tag {};
178 struct member_ptr_tag {};
179 struct function_obj_ref_tag {};
180 struct stateless_function_obj_tag {};
183 class get_function_tag
185 typedef typename ct_if<(is_pointer<F>::value),
187 function_obj_tag>::type ptr_or_obj_tag;
189 typedef typename ct_if<(is_member_pointer<F>::value),
191 ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
193 typedef typename ct_if<(is_reference_wrapper<F>::value),
194 function_obj_ref_tag,
195 ptr_or_obj_or_mem_tag>::type or_ref_tag;
198 typedef typename ct_if<(is_stateless<F>::value),
199 stateless_function_obj_tag,
200 or_ref_tag>::type type;
203 // The trivial manager does nothing but return the same pointer (if we
204 // are cloning) or return the null pointer (if we are deleting).
206 struct trivial_manager
208 static inline any_pointer
209 get(any_pointer f, functor_manager_operation_type op)
212 case clone_functor_tag: return f;
214 case destroy_functor_tag:
215 return make_any_pointer(reinterpret_cast<void*>(0));
217 case check_functor_type_tag:
219 std::type_info* t = static_cast<std::type_info*>(f.obj_ptr);
220 return BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(F), *t)?
222 : make_any_pointer(reinterpret_cast<void*>(0));
226 // Clears up a warning with GCC 3.2.3
227 return make_any_pointer(reinterpret_cast<void*>(0));
232 * The functor_manager class contains a static function "manage" which
233 * can clone or destroy the given function/function object pointer.
235 template<typename Functor, typename Allocator>
236 struct functor_manager
239 typedef Functor functor_type;
241 // For function pointers, the manager is trivial
242 static inline any_pointer
243 manager(any_pointer function_ptr,
244 functor_manager_operation_type op,
247 if (op == clone_functor_tag)
250 return make_any_pointer(static_cast<void (*)()>(0));
253 // For function object pointers, we clone the pointer to each
254 // function has its own version.
255 static inline any_pointer
256 manager(any_pointer function_obj_ptr,
257 functor_manager_operation_type op,
260 #ifndef BOOST_NO_STD_ALLOCATOR
261 typedef typename Allocator::template rebind<functor_type>::other
263 typedef typename allocator_type::pointer pointer_type;
265 typedef functor_type* pointer_type;
266 #endif // BOOST_NO_STD_ALLOCATOR
268 # ifndef BOOST_NO_STD_ALLOCATOR
269 allocator_type allocator;
270 # endif // BOOST_NO_STD_ALLOCATOR
272 if (op == clone_functor_tag) {
274 static_cast<functor_type*>(function_obj_ptr.obj_ptr);
277 # ifndef BOOST_NO_STD_ALLOCATOR
278 pointer_type copy = allocator.allocate(1);
279 allocator.construct(copy, *f);
281 // Get back to the original pointer type
282 functor_type* new_f = static_cast<functor_type*>(copy);
284 functor_type* new_f = new functor_type(*f);
285 # endif // BOOST_NO_STD_ALLOCATOR
286 return make_any_pointer(static_cast<void*>(new_f));
289 /* Cast from the void pointer to the functor pointer type */
291 reinterpret_cast<functor_type*>(function_obj_ptr.obj_ptr);
293 # ifndef BOOST_NO_STD_ALLOCATOR
294 /* Cast from the functor pointer type to the allocator's pointer
296 pointer_type victim = static_cast<pointer_type>(f);
298 // Destroy and deallocate the functor
299 allocator.destroy(victim);
300 allocator.deallocate(victim, 1);
303 # endif // BOOST_NO_STD_ALLOCATOR
305 return make_any_pointer(static_cast<void*>(0));
309 /* Dispatch to an appropriate manager based on whether we have a
310 function pointer or a function object pointer. */
312 manage(any_pointer functor_ptr, functor_manager_operation_type op)
314 if (op == check_functor_type_tag) {
315 std::type_info* type =
316 static_cast<std::type_info*>(functor_ptr.obj_ptr);
317 return (BOOST_FUNCTION_COMPARE_TYPE_ID(typeid(Functor), *type)?
319 : make_any_pointer(reinterpret_cast<void*>(0)));
322 typedef typename get_function_tag<functor_type>::type tag_type;
323 return manager(functor_ptr, op, tag_type());
328 // A type that is only used for comparisons against zero
329 struct useless_clear_type {};
331 #ifdef BOOST_NO_SFINAE
332 // These routines perform comparisons between a Boost.Function
333 // object and an arbitrary function object (when the last
334 // parameter is mpl::bool_<false>) or against zero (when the
335 // last parameter is mpl::bool_<true>). They are only necessary
336 // for compilers that don't support SFINAE.
337 template<typename Function, typename Functor>
339 compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
340 { return f.empty(); }
342 template<typename Function, typename Functor>
344 compare_not_equal(const Function& f, const Functor&, int,
346 { return !f.empty(); }
348 template<typename Function, typename Functor>
350 compare_equal(const Function& f, const Functor& g, long,
353 if (const Functor* fp = f.template target<Functor>())
354 return function_equal(*fp, g);
358 template<typename Function, typename Functor>
360 compare_equal(const Function& f, const reference_wrapper<Functor>& g,
361 int, mpl::bool_<false>)
363 if (const Functor* fp = f.template target<Functor>())
364 return fp == g.get_pointer();
368 template<typename Function, typename Functor>
370 compare_not_equal(const Function& f, const Functor& g, long,
373 if (const Functor* fp = f.template target<Functor>())
374 return !function_equal(*fp, g);
378 template<typename Function, typename Functor>
380 compare_not_equal(const Function& f,
381 const reference_wrapper<Functor>& g, int,
384 if (const Functor* fp = f.template target<Functor>())
385 return fp != g.get_pointer();
388 #endif // BOOST_NO_SFINAE
389 } // end namespace function
390 } // end namespace detail
393 * The function_base class contains the basic elements needed for the
394 * function1, function2, function3, etc. classes. It is common to all
395 * functions (and as such can be used to tell if we have one of the
396 * functionN objects).
401 function_base() : manager(0)
406 // Is this function empty?
407 bool empty() const { return !manager; }
409 template<typename Functor>
412 if (!manager) return 0;
414 detail::function::any_pointer result =
415 manager(detail::function::make_any_pointer(&typeid(Functor)),
416 detail::function::check_functor_type_tag);
417 if (!result.obj_ptr) return 0;
419 typedef typename detail::function::get_function_tag<Functor>::type tag;
420 return get_functor_pointer<Functor>(tag(), 0);
424 template<typename Functor>
426 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
427 const Functor* target( Functor * = 0 ) const
429 const Functor* target() const
432 if (!manager) return 0;
434 detail::function::any_pointer result =
435 manager(detail::function::make_any_pointer(&typeid(Functor)),
436 detail::function::check_functor_type_tag);
437 if (!result.obj_ptr) return 0;
439 typedef typename detail::function::get_function_tag<Functor>::type tag;
441 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
442 return get_functor_pointer(tag(), 0, (Functor*)0);
444 return get_functor_pointer<Functor>(tag(), 0);
450 bool contains(const F& f) const
452 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
453 if (const F* fp = this->target( (F*)0 )) {
455 if (const F* fp = this->template target<F>()) {
457 return function_equal(*fp, f);
463 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
464 // GCC 3.3 and newer cannot copy with the global operator==, due to
465 // problems with instantiation of function return types before it
466 // has been verified that the argument types match up.
467 template<typename Functor>
468 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
469 operator==(Functor g) const
471 if (const Functor* fp = target<Functor>())
472 return function_equal(*fp, g);
476 template<typename Functor>
477 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
478 operator!=(Functor g) const
480 if (const Functor* fp = target<Functor>())
481 return !function_equal(*fp, g);
486 public: // should be protected, but GCC 2.95.3 will fail to allow access
487 detail::function::any_pointer (*manager)(
488 detail::function::any_pointer,
489 detail::function::functor_manager_operation_type);
490 detail::function::any_pointer functor;
493 template<typename Functor>
494 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
495 Functor* get_functor_pointer(detail::function::function_ptr_tag, int, Functor * = 0)
497 Functor* get_functor_pointer(detail::function::function_ptr_tag, int)
499 { return reinterpret_cast<Functor*>(&functor.func_ptr); }
501 template<typename Functor, typename Tag>
502 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
503 Functor* get_functor_pointer(Tag, long, Functor * = 0)
505 Functor* get_functor_pointer(Tag, long)
507 { return static_cast<Functor*>(functor.obj_ptr); }
509 template<typename Functor>
511 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
512 get_functor_pointer(detail::function::function_ptr_tag, int, Functor * = 0) const
514 get_functor_pointer(detail::function::function_ptr_tag, int) const
516 { return reinterpret_cast<const Functor*>(&functor.func_ptr); }
518 template<typename Functor, typename Tag>
519 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
520 const Functor* get_functor_pointer(Tag, long, Functor * = 0) const
522 const Functor* get_functor_pointer(Tag, long) const
524 { return static_cast<const Functor*>(functor.const_obj_ptr); }
528 * The bad_function_call exception class is thrown when a boost::function
531 class bad_function_call : public std::runtime_error
534 bad_function_call() : std::runtime_error("call to empty boost::function") {}
537 #ifndef BOOST_NO_SFINAE
538 inline bool operator==(const function_base& f,
539 detail::function::useless_clear_type*)
544 inline bool operator!=(const function_base& f,
545 detail::function::useless_clear_type*)
550 inline bool operator==(detail::function::useless_clear_type*,
551 const function_base& f)
556 inline bool operator!=(detail::function::useless_clear_type*,
557 const function_base& f)
563 #ifdef BOOST_NO_SFINAE
564 // Comparisons between boost::function objects and arbitrary function objects
565 template<typename Functor>
566 inline bool operator==(const function_base& f, Functor g)
568 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
569 return detail::function::compare_equal(f, g, 0, integral());
572 template<typename Functor>
573 inline bool operator==(Functor g, const function_base& f)
575 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
576 return detail::function::compare_equal(f, g, 0, integral());
579 template<typename Functor>
580 inline bool operator!=(const function_base& f, Functor g)
582 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
583 return detail::function::compare_not_equal(f, g, 0, integral());
586 template<typename Functor>
587 inline bool operator!=(Functor g, const function_base& f)
589 typedef mpl::bool_<(is_integral<Functor>::value)> integral;
590 return detail::function::compare_not_equal(f, g, 0, integral());
594 # if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
595 // Comparisons between boost::function objects and arbitrary function
596 // objects. GCC 3.3 and before has an obnoxious bug that prevents this
598 template<typename Functor>
599 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
600 operator==(const function_base& f, Functor g)
602 if (const Functor* fp = f.template target<Functor>())
603 return function_equal(*fp, g);
607 template<typename Functor>
608 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
609 operator==(Functor g, const function_base& f)
611 if (const Functor* fp = f.template target<Functor>())
612 return function_equal(g, *fp);
616 template<typename Functor>
617 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
618 operator!=(const function_base& f, Functor g)
620 if (const Functor* fp = f.template target<Functor>())
621 return !function_equal(*fp, g);
625 template<typename Functor>
626 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
627 operator!=(Functor g, const function_base& f)
629 if (const Functor* fp = f.template target<Functor>())
630 return !function_equal(g, *fp);
635 template<typename Functor>
636 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
637 operator==(const function_base& f, reference_wrapper<Functor> g)
639 if (const Functor* fp = f.template target<Functor>())
640 return fp == g.get_pointer();
644 template<typename Functor>
645 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
646 operator==(reference_wrapper<Functor> g, const function_base& f)
648 if (const Functor* fp = f.template target<Functor>())
649 return g.get_pointer() == fp;
653 template<typename Functor>
654 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
655 operator!=(const function_base& f, reference_wrapper<Functor> g)
657 if (const Functor* fp = f.template target<Functor>())
658 return fp != g.get_pointer();
662 template<typename Functor>
663 BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
664 operator!=(reference_wrapper<Functor> g, const function_base& f)
666 if (const Functor* fp = f.template target<Functor>())
667 return g.get_pointer() != fp;
671 #endif // Compiler supporting SFINAE
675 inline bool has_empty_target(const function_base* f)
680 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
681 inline bool has_empty_target(const void*)
686 inline bool has_empty_target(...)
691 } // end namespace function
692 } // end namespace detail
693 } // end namespace boost
695 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
696 #undef BOOST_FUNCTION_COMPARE_TYPE_ID
698 #endif // BOOST_FUNCTION_BASE_HEADER