1 // Boost.Function library
3 // Copyright Doug Gregor 2001-2003. 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
17 #include <boost/config.hpp>
18 #include <boost/assert.hpp>
19 #include <boost/type_traits/arithmetic_traits.hpp>
20 #include <boost/type_traits/composite_traits.hpp>
21 #include <boost/type_traits/is_stateless.hpp>
22 #include <boost/ref.hpp>
23 #include <boost/pending/ct_if.hpp>
24 #include <boost/detail/workaround.hpp>
26 #ifndef BOOST_NO_SFINAE
27 # include "boost/utility/enable_if.hpp"
30 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
31 # define BOOST_FUNCTION_TARGET_FIX(x) x
33 # define BOOST_FUNCTION_TARGET_FIX(x)
36 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
37 // Work around a compiler bug.
38 // boost::python::objects::function has to be seen by the compiler before the
39 // boost::function class template.
40 namespace boost { namespace python { namespace objects {
45 #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
46 || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
47 || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
48 # define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
51 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
54 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
55 // The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
58 template<typename Signature,
59 typename Allocator = std::allocator<function_base> >
62 template<typename Signature, typename Allocator = std::allocator<void> >
66 template<typename Signature, typename Allocator>
67 inline void swap(function<Signature, Allocator>& f1,
68 function<Signature, Allocator>& f2)
73 } // end namespace boost
74 #endif // have partial specialization
80 * A union of a function pointer and a void pointer. This is necessary
81 * because 5.2.10/6 allows reinterpret_cast<> to safely cast between
82 * function pointer types and 5.2.9/10 allows static_cast<> to safely
83 * cast between a void pointer and an object pointer. But it is not legal
84 * to cast between a function pointer and a void* (in either direction),
85 * so function requires a union of the two. */
89 const void* const_obj_ptr;
94 inline any_pointer make_any_pointer(void* o)
101 inline any_pointer make_any_pointer(const void* o)
108 inline any_pointer make_any_pointer(void (*f)())
116 * The unusable class is a placeholder for unused function arguments
117 * It is also completely unusable except that it constructable from
118 * anything. This helps compilers without partial specialization to
119 * handle Boost.Function objects returning void.
124 template<typename T> unusable(const T&) {}
127 /* Determine the return type. This supports compilers that do not support
128 * void returns or partial specialization by silently changing the return
129 * type to "unusable".
131 template<typename T> struct function_return_type { typedef T type; };
134 struct function_return_type<void>
136 typedef unusable type;
139 // The operation type to perform on the given functor/function pointer
140 enum functor_manager_operation_type {
145 // Tags used to decide between different types of functions
146 struct function_ptr_tag {};
147 struct function_obj_tag {};
148 struct member_ptr_tag {};
149 struct function_obj_ref_tag {};
150 struct stateless_function_obj_tag {};
153 class get_function_tag
155 typedef typename ct_if<(is_pointer<F>::value),
157 function_obj_tag>::type ptr_or_obj_tag;
159 typedef typename ct_if<(is_member_pointer<F>::value),
161 ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
163 typedef typename ct_if<(is_reference_wrapper<F>::value),
164 function_obj_ref_tag,
165 ptr_or_obj_or_mem_tag>::type or_ref_tag;
168 typedef typename ct_if<(is_stateless<F>::value),
169 stateless_function_obj_tag,
170 or_ref_tag>::type type;
173 // The trivial manager does nothing but return the same pointer (if we
174 // are cloning) or return the null pointer (if we are deleting).
175 inline any_pointer trivial_manager(any_pointer f,
176 functor_manager_operation_type op)
178 if (op == clone_functor_tag)
181 return make_any_pointer(reinterpret_cast<void*>(0));
185 * The functor_manager class contains a static function "manage" which
186 * can clone or destroy the given function/function object pointer.
188 template<typename Functor, typename Allocator>
189 struct functor_manager
192 typedef Functor functor_type;
194 // For function pointers, the manager is trivial
195 static inline any_pointer
196 manager(any_pointer function_ptr,
197 functor_manager_operation_type op,
200 if (op == clone_functor_tag)
203 return make_any_pointer(static_cast<void (*)()>(0));
206 // For function object pointers, we clone the pointer to each
207 // function has its own version.
208 static inline any_pointer
209 manager(any_pointer function_obj_ptr,
210 functor_manager_operation_type op,
213 #ifndef BOOST_NO_STD_ALLOCATOR
214 typedef typename Allocator::template rebind<functor_type>::other
216 typedef typename allocator_type::pointer pointer_type;
218 typedef functor_type* pointer_type;
219 #endif // BOOST_NO_STD_ALLOCATOR
221 # ifndef BOOST_NO_STD_ALLOCATOR
222 allocator_type allocator;
223 # endif // BOOST_NO_STD_ALLOCATOR
225 if (op == clone_functor_tag) {
227 static_cast<functor_type*>(function_obj_ptr.obj_ptr);
230 # ifndef BOOST_NO_STD_ALLOCATOR
231 pointer_type copy = allocator.allocate(1);
232 allocator.construct(copy, *f);
234 // Get back to the original pointer type
235 functor_type* new_f = static_cast<functor_type*>(copy);
237 functor_type* new_f = new functor_type(*f);
238 # endif // BOOST_NO_STD_ALLOCATOR
239 return make_any_pointer(static_cast<void*>(new_f));
242 /* Cast from the void pointer to the functor pointer type */
244 reinterpret_cast<functor_type*>(function_obj_ptr.obj_ptr);
246 # ifndef BOOST_NO_STD_ALLOCATOR
247 /* Cast from the functor pointer type to the allocator's pointer
249 pointer_type victim = static_cast<pointer_type>(f);
251 // Destroy and deallocate the functor
252 allocator.destroy(victim);
253 allocator.deallocate(victim, 1);
256 # endif // BOOST_NO_STD_ALLOCATOR
258 return make_any_pointer(static_cast<void*>(0));
262 /* Dispatch to an appropriate manager based on whether we have a
263 function pointer or a function object pointer. */
265 manage(any_pointer functor_ptr, functor_manager_operation_type op)
267 typedef typename get_function_tag<functor_type>::type tag_type;
268 return manager(functor_ptr, op, tag_type());
272 // A type that is only used for comparisons against zero
273 struct useless_clear_type {};
274 } // end namespace function
275 } // end namespace detail
278 * The function_base class contains the basic elements needed for the
279 * function1, function2, function3, etc. classes. It is common to all
280 * functions (and as such can be used to tell if we have one of the
281 * functionN objects).
286 function_base() : manager(0)
291 // Is this function empty?
292 bool empty() const { return !manager; }
294 public: // should be protected, but GCC 2.95.3 will fail to allow access
295 detail::function::any_pointer (*manager)(
296 detail::function::any_pointer,
297 detail::function::functor_manager_operation_type);
298 detail::function::any_pointer functor;
302 * The bad_function_call exception class is thrown when a boost::function
305 class bad_function_call : public std::runtime_error
308 bad_function_call() : std::runtime_error("call to empty boost::function") {}
311 /* Poison comparison between Boost.Function objects (because it is
312 * meaningless). The comparisons would otherwise be allowed because of the
313 * conversion required to allow syntax such as:
314 * boost::function<int, int> f;
317 void operator==(const function_base&, const function_base&);
318 void operator!=(const function_base&, const function_base&);
320 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
321 inline bool operator==(const function_base& f,
322 detail::function::useless_clear_type*)
327 inline bool operator!=(const function_base& f,
328 detail::function::useless_clear_type*)
333 inline bool operator==(detail::function::useless_clear_type*,
334 const function_base& f)
339 inline bool operator!=(detail::function::useless_clear_type*,
340 const function_base& f)
348 inline bool has_empty_target(const function_base* f)
353 inline bool has_empty_target(...)
357 } // end namespace function
358 } // end namespace detail
359 } // end namespace boost
361 #endif // BOOST_FUNCTION_BASE_HEADER