1 // Boost.Function library
3 // Copyright (C) 2001-2003 Doug Gregor (gregod@cs.rpi.edu)
5 // Permission to copy, use, sell and distribute this software is granted
6 // provided this copyright notice appears in all copies.
7 // Permission to modify the code and to distribute modified code is granted
8 // provided this copyright notice appears in all copies, and a notice
9 // that the code was modified is included with the copyright notice.
11 // This software is provided "as is" without express or implied warranty,
12 // and with no claim as to its suitability for any purpose.
14 // For more information, see http://www.boost.org
16 #ifndef BOOST_FUNCTION_BASE_HEADER
17 #define BOOST_FUNCTION_BASE_HEADER
23 #include <boost/config.hpp>
24 #include <boost/assert.hpp>
25 #include <boost/type_traits/arithmetic_traits.hpp>
26 #include <boost/type_traits/composite_traits.hpp>
27 #include <boost/type_traits/is_stateless.hpp>
28 #include <boost/ref.hpp>
29 #include <boost/pending/ct_if.hpp>
30 #include <boost/detail/workaround.hpp>
32 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
33 # define BOOST_FUNCTION_TARGET_FIX(x) x
35 # define BOOST_FUNCTION_TARGET_FIX(x)
38 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
39 // Work around a compiler bug.
40 // boost::python::objects::function has to be seen by the compiler before the
41 // boost::function class template.
42 namespace boost { namespace python { namespace objects {
47 // GCC 2.95.3 (or earlier) doesn't support enable_if
48 #if BOOST_WORKAROUND(__GNUC__, < 3)
49 # define BOOST_FUNCTION_NO_ENABLE_IF
52 // MIPSpro 7.3.1.3m doesn't support enable_if
53 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
54 # define BOOST_FUNCTION_NO_ENABLE_IF
57 // MSVC 7.0 doesn't support enable_if
58 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && !defined(BOOST_STRICT_CONFIG)
59 # define BOOST_FUNCTION_NO_ENABLE_IF
62 // Borland C++ 5.6.0 doesn't support enable_if
63 #if BOOST_WORKAROUND(__BORLANDC__, <= 0x562)
64 # define BOOST_FUNCTION_NO_ENABLE_IF
67 // Metrowerks 7.2 doesn't support enable_if
68 #if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
69 # define BOOST_FUNCTION_NO_ENABLE_IF
72 #if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x540)
73 # define BOOST_FUNCTION_NO_ENABLE_IF
76 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
79 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
80 // The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
83 template<typename Signature,
84 typename Allocator = std::allocator<function_base> >
87 template<typename Signature, typename Allocator = std::allocator<void> >
91 template<typename Signature, typename Allocator>
92 inline void swap(function<Signature, Allocator>& f1,
93 function<Signature, Allocator>& f2)
98 } // end namespace boost
99 #endif // have partial specialization
105 * A union of a function pointer and a void pointer. This is necessary
106 * because 5.2.10/6 allows reinterpret_cast<> to safely cast between
107 * function pointer types and 5.2.9/10 allows static_cast<> to safely
108 * cast between a void pointer and an object pointer. But it is not legal
109 * to cast between a function pointer and a void* (in either direction),
110 * so function requires a union of the two. */
114 const void* const_obj_ptr;
119 inline any_pointer make_any_pointer(void* o)
126 inline any_pointer make_any_pointer(const void* o)
133 inline any_pointer make_any_pointer(void (*f)())
141 * The unusable class is a placeholder for unused function arguments
142 * It is also completely unusable except that it constructable from
143 * anything. This helps compilers without partial specialization to
144 * handle Boost.Function objects returning void.
149 template<typename T> unusable(const T&) {}
152 /* Determine the return type. This supports compilers that do not support
153 * void returns or partial specialization by silently changing the return
154 * type to "unusable".
156 template<typename T> struct function_return_type { typedef T type; };
159 struct function_return_type<void>
161 typedef unusable type;
164 // The operation type to perform on the given functor/function pointer
165 enum functor_manager_operation_type {
170 // Tags used to decide between different types of functions
171 struct function_ptr_tag {};
172 struct function_obj_tag {};
173 struct member_ptr_tag {};
174 struct function_obj_ref_tag {};
175 struct stateless_function_obj_tag {};
178 class get_function_tag
180 typedef typename ct_if<(is_pointer<F>::value),
182 function_obj_tag>::type ptr_or_obj_tag;
184 typedef typename ct_if<(is_member_pointer<F>::value),
186 ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
188 typedef typename ct_if<(is_reference_wrapper<F>::value),
189 function_obj_ref_tag,
190 ptr_or_obj_or_mem_tag>::type or_ref_tag;
193 typedef typename ct_if<(is_stateless<F>::value),
194 stateless_function_obj_tag,
195 or_ref_tag>::type type;
198 // The trivial manager does nothing but return the same pointer (if we
199 // are cloning) or return the null pointer (if we are deleting).
200 inline any_pointer trivial_manager(any_pointer f,
201 functor_manager_operation_type op)
203 if (op == clone_functor_tag)
206 return make_any_pointer(reinterpret_cast<void*>(0));
210 * The functor_manager class contains a static function "manage" which
211 * can clone or destroy the given function/function object pointer.
213 template<typename Functor, typename Allocator>
214 struct functor_manager
217 typedef Functor functor_type;
219 // For function pointers, the manager is trivial
220 static inline any_pointer
221 manager(any_pointer function_ptr,
222 functor_manager_operation_type op,
225 if (op == clone_functor_tag)
228 return make_any_pointer(static_cast<void (*)()>(0));
231 // For function object pointers, we clone the pointer to each
232 // function has its own version.
233 static inline any_pointer
234 manager(any_pointer function_obj_ptr,
235 functor_manager_operation_type op,
238 #ifndef BOOST_NO_STD_ALLOCATOR
239 typedef typename Allocator::template rebind<functor_type>::other
241 typedef typename allocator_type::pointer pointer_type;
243 typedef functor_type* pointer_type;
244 #endif // BOOST_NO_STD_ALLOCATOR
246 # ifndef BOOST_NO_STD_ALLOCATOR
247 allocator_type allocator;
248 # endif // BOOST_NO_STD_ALLOCATOR
250 if (op == clone_functor_tag) {
252 static_cast<functor_type*>(function_obj_ptr.obj_ptr);
255 # ifndef BOOST_NO_STD_ALLOCATOR
256 pointer_type copy = allocator.allocate(1);
257 allocator.construct(copy, *f);
259 // Get back to the original pointer type
260 functor_type* new_f = static_cast<functor_type*>(copy);
262 functor_type* new_f = new functor_type(*f);
263 # endif // BOOST_NO_STD_ALLOCATOR
264 return make_any_pointer(static_cast<void*>(new_f));
267 /* Cast from the void pointer to the functor pointer type */
269 reinterpret_cast<functor_type*>(function_obj_ptr.obj_ptr);
271 # ifndef BOOST_NO_STD_ALLOCATOR
272 /* Cast from the functor pointer type to the allocator's pointer
274 pointer_type victim = static_cast<pointer_type>(f);
276 // Destroy and deallocate the functor
277 allocator.destroy(victim);
278 allocator.deallocate(victim, 1);
281 # endif // BOOST_NO_STD_ALLOCATOR
283 return make_any_pointer(static_cast<void*>(0));
287 /* Dispatch to an appropriate manager based on whether we have a
288 function pointer or a function object pointer. */
290 manage(any_pointer functor_ptr, functor_manager_operation_type op)
292 typedef typename get_function_tag<functor_type>::type tag_type;
293 return manager(functor_ptr, op, tag_type());
297 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
298 template<bool cond, typename T> struct enable_if;
299 template<typename T> struct enable_if<true, T> { typedef T type; };
300 template<typename T> struct enable_if<false, T> {};
313 struct enabled<false>
321 template<bool Enabled, typename T>
322 struct enable_if : public enabled<Enabled>::template base<T>
327 // A type that is only used for comparisons against zero
328 struct useless_clear_type {};
329 } // end namespace function
330 } // end namespace detail
333 * The function_base class contains the basic elements needed for the
334 * function1, function2, function3, etc. classes. It is common to all
335 * functions (and as such can be used to tell if we have one of the
336 * functionN objects).
341 function_base() : manager(0)
346 // Is this function empty?
347 bool empty() const { return !manager; }
349 public: // should be protected, but GCC 2.95.3 will fail to allow access
350 detail::function::any_pointer (*manager)(
351 detail::function::any_pointer,
352 detail::function::functor_manager_operation_type);
353 detail::function::any_pointer functor;
357 * The bad_function_call exception class is thrown when a boost::function
360 class bad_function_call : public std::runtime_error
363 bad_function_call() : std::runtime_error("call to empty boost::function") {}
366 /* Poison comparison between Boost.Function objects (because it is
367 * meaningless). The comparisons would otherwise be allowed because of the
368 * conversion required to allow syntax such as:
369 * boost::function<int, int> f;
372 void operator==(const function_base&, const function_base&);
373 void operator!=(const function_base&, const function_base&);
375 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
376 inline bool operator==(const function_base& f,
377 detail::function::useless_clear_type*)
382 inline bool operator!=(const function_base& f,
383 detail::function::useless_clear_type*)
388 inline bool operator==(detail::function::useless_clear_type*,
389 const function_base& f)
394 inline bool operator!=(detail::function::useless_clear_type*,
395 const function_base& f)
403 inline bool has_empty_target(const function_base* f)
408 inline bool has_empty_target(...)
412 } // end namespace function
413 } // end namespace detail
414 } // end namespace boost
416 #endif // BOOST_FUNCTION_BASE_HEADER