1 // Boost.Function library
3 // Copyright Douglas 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 // Note: this header is a header template and must NOT have multiple-inclusion
12 #include <boost/function/detail/prologue.hpp>
14 #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
16 #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
18 #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
20 #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
22 #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
24 #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
25 typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(arg, BOOST_PP_CAT(BOOST_PP_INC(I),_type));
27 #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
29 // Type of the default allocator
30 #ifndef BOOST_NO_STD_ALLOCATOR
31 # define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
33 # define BOOST_FUNCTION_DEFAULT_ALLOCATOR int
34 #endif // BOOST_NO_STD_ALLOCATOR
36 // Comma if nonzero number of arguments
37 #if BOOST_FUNCTION_NUM_ARGS == 0
38 # define BOOST_FUNCTION_COMMA
40 # define BOOST_FUNCTION_COMMA ,
41 #endif // BOOST_FUNCTION_NUM_ARGS > 0
43 // Class names used in this version of the code
44 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
45 #define BOOST_FUNCTION_FUNCTION_INVOKER \
46 BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
47 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
48 BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
49 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
50 BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
51 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
52 BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
53 #define BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER \
54 BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
55 #define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \
56 BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
57 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
58 BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
59 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
60 BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
61 #define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \
62 BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
64 #ifndef BOOST_NO_VOID_RETURNS
65 # define BOOST_FUNCTION_VOID_RETURN_TYPE void
66 # define BOOST_FUNCTION_RETURN(X) X
68 # define BOOST_FUNCTION_VOID_RETURN_TYPE ::boost::detail::function::unusable
69 # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
77 typename R BOOST_FUNCTION_COMMA
78 BOOST_FUNCTION_TEMPLATE_PARMS
80 struct BOOST_FUNCTION_FUNCTION_INVOKER
82 static R invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
85 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
86 return f(BOOST_FUNCTION_ARGS);
92 typename R BOOST_FUNCTION_COMMA
93 BOOST_FUNCTION_TEMPLATE_PARMS
95 struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
97 static BOOST_FUNCTION_VOID_RETURN_TYPE
98 invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
102 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
103 BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
108 typename FunctionObj,
109 typename R BOOST_FUNCTION_COMMA
110 BOOST_FUNCTION_TEMPLATE_PARMS
112 struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
114 static R invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
115 BOOST_FUNCTION_PARMS)
118 FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
119 return (*f)(BOOST_FUNCTION_ARGS);
124 typename FunctionObj,
125 typename R BOOST_FUNCTION_COMMA
126 BOOST_FUNCTION_TEMPLATE_PARMS
128 struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
130 static BOOST_FUNCTION_VOID_RETURN_TYPE
131 invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
132 BOOST_FUNCTION_PARMS)
135 FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
136 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
141 typename FunctionObj,
142 typename R BOOST_FUNCTION_COMMA
143 BOOST_FUNCTION_TEMPLATE_PARMS
145 struct BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
147 static R invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
149 FunctionObj f = FunctionObj();
150 return f(BOOST_FUNCTION_ARGS);
155 typename FunctionObj,
156 typename R BOOST_FUNCTION_COMMA
157 BOOST_FUNCTION_TEMPLATE_PARMS
159 struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
161 static BOOST_FUNCTION_VOID_RETURN_TYPE
162 invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
165 FunctionObj f = FunctionObj();
166 BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
171 typename FunctionPtr,
172 typename R BOOST_FUNCTION_COMMA
173 BOOST_FUNCTION_TEMPLATE_PARMS
175 struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
177 typedef typename ct_if<(is_void<R>::value),
178 BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
180 R BOOST_FUNCTION_COMMA
181 BOOST_FUNCTION_TEMPLATE_ARGS
183 BOOST_FUNCTION_FUNCTION_INVOKER<
185 R BOOST_FUNCTION_COMMA
186 BOOST_FUNCTION_TEMPLATE_ARGS
192 typename FunctionObj,
193 typename R BOOST_FUNCTION_COMMA
194 BOOST_FUNCTION_TEMPLATE_PARMS
196 struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
198 typedef typename ct_if<(is_void<R>::value),
199 BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
201 R BOOST_FUNCTION_COMMA
202 BOOST_FUNCTION_TEMPLATE_ARGS
204 BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
206 R BOOST_FUNCTION_COMMA
207 BOOST_FUNCTION_TEMPLATE_ARGS
213 typename FunctionObj,
214 typename R BOOST_FUNCTION_COMMA
215 BOOST_FUNCTION_TEMPLATE_PARMS
217 struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
219 typedef typename ct_if<(is_void<R>::value),
220 BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER<
222 R BOOST_FUNCTION_COMMA
223 BOOST_FUNCTION_TEMPLATE_ARGS
225 BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER<
227 R BOOST_FUNCTION_COMMA
228 BOOST_FUNCTION_TEMPLATE_ARGS
233 } // end namespace function
234 } // end namespace detail
237 typename R BOOST_FUNCTION_COMMA
238 BOOST_FUNCTION_TEMPLATE_PARMS,
239 typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
241 class BOOST_FUNCTION_FUNCTION : public function_base
244 #ifndef BOOST_NO_VOID_RETURNS
245 typedef R result_type;
247 typedef typename detail::function::function_return_type<R>::type
249 #endif // BOOST_NO_VOID_RETURNS
252 struct clear_type {};
255 BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
257 // add signature for boost::lambda
258 template<typename Args>
261 typedef result_type type;
264 #if BOOST_FUNCTION_NUM_ARGS == 1
265 typedef T0 argument_type;
266 #elif BOOST_FUNCTION_NUM_ARGS == 2
267 typedef T0 first_argument_type;
268 typedef T1 second_argument_type;
271 BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
272 BOOST_FUNCTION_ARG_TYPES
274 typedef Allocator allocator_type;
275 typedef BOOST_FUNCTION_FUNCTION self_type;
277 BOOST_FUNCTION_FUNCTION() : function_base()
280 // MSVC chokes if the following two constructors are collapsed into
281 // one with a default parameter.
282 template<typename Functor>
283 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
284 #ifndef BOOST_NO_SFINAE
285 ,typename enable_if_c<
286 (::boost::type_traits::ice_not<
287 (is_integral<Functor>::value)>::value),
289 #endif // BOOST_NO_SFINAE
297 #ifndef BOOST_NO_SFINAE
298 BOOST_FUNCTION_FUNCTION(clear_type*) : function_base(), invoker(0) {}
300 BOOST_FUNCTION_FUNCTION(int zero) : function_base(), invoker(0)
302 BOOST_ASSERT(zero == 0);
306 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
310 this->assign_to_own(f);
313 ~BOOST_FUNCTION_FUNCTION() { clear(); }
315 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
316 // MSVC 6.0 and prior require all definitions to be inline, but
317 // these definitions can become very costly.
318 result_type operator()(BOOST_FUNCTION_PARMS) const
321 boost::throw_exception(bad_function_call());
323 return invoker(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
326 result_type operator()(BOOST_FUNCTION_PARMS) const;
329 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
330 // when to use self_type is obnoxious. MSVC cannot handle self_type as
331 // the return type of these assignment operators, but Borland C++ cannot
332 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
334 template<typename Functor>
335 #ifndef BOOST_NO_SFINAE
336 typename enable_if_c<
337 (::boost::type_traits::ice_not<
338 (is_integral<Functor>::value)>::value),
339 BOOST_FUNCTION_FUNCTION&>::type
341 BOOST_FUNCTION_FUNCTION&
343 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
345 self_type(f).swap(*this);
349 #ifndef BOOST_NO_SFINAE
350 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
356 BOOST_FUNCTION_FUNCTION& operator=(int zero)
358 BOOST_ASSERT(zero == 0);
364 // Assignment from another BOOST_FUNCTION_FUNCTION
365 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
370 self_type(f).swap(*this);
374 void swap(BOOST_FUNCTION_FUNCTION& other)
379 std::swap(this->manager, other.manager);
380 std::swap(this->functor, other.functor);
381 std::swap(invoker, other.invoker);
384 // Clear out a target, if there is one
388 function_base::functor =
389 this->manager(this->functor, detail::function::destroy_functor_tag);
396 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
397 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
398 operator bool () const { return !this->empty(); }
405 typedef void (dummy::*safe_bool)();
408 operator safe_bool () const
409 { return (this->empty())? 0 : &dummy::nonnull; }
411 bool operator!() const
412 { return this->empty(); }
416 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
420 this->manager = f.manager;
422 f.manager(f.functor, detail::function::clone_functor_tag);
426 template<typename Functor>
427 void assign_to(Functor f)
429 typedef typename detail::function::get_function_tag<Functor>::type tag;
430 this->assign_to(f, tag());
433 template<typename FunctionPtr>
434 void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
439 typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
441 R BOOST_FUNCTION_COMMA
442 BOOST_FUNCTION_TEMPLATE_ARGS
446 invoker = &actual_invoker_type::invoke;
448 &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
450 this->manager(detail::function::make_any_pointer(
451 // should be a reinterpret cast, but some compilers
452 // insist on giving cv-qualifiers to free functions
455 detail::function::clone_functor_tag);
459 #if BOOST_FUNCTION_NUM_ARGS > 0
460 template<typename MemberPtr>
461 void assign_to(MemberPtr f, detail::function::member_ptr_tag)
463 this->assign_to(mem_fn(f));
465 #endif // BOOST_FUNCTION_NUM_ARGS > 0
467 template<typename FunctionObj>
468 void assign_to(FunctionObj f, detail::function::function_obj_tag)
470 if (!detail::function::has_empty_target(boost::addressof(f))) {
472 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
474 R BOOST_FUNCTION_COMMA
475 BOOST_FUNCTION_TEMPLATE_ARGS
479 invoker = &actual_invoker_type::invoke;
480 this->manager = &detail::function::functor_manager<
481 FunctionObj, Allocator>::manage;
482 #ifndef BOOST_NO_STD_ALLOCATOR
483 typedef typename Allocator::template rebind<FunctionObj>::other
484 rebound_allocator_type;
485 typedef typename rebound_allocator_type::pointer pointer_type;
486 rebound_allocator_type allocator;
487 pointer_type copy = allocator.allocate(1);
488 allocator.construct(copy, f);
490 // Get back to the original pointer type
491 FunctionObj* new_f = static_cast<FunctionObj*>(copy);
493 FunctionObj* new_f = new FunctionObj(f);
494 #endif // BOOST_NO_STD_ALLOCATOR
496 detail::function::make_any_pointer(static_cast<void*>(new_f));
500 template<typename FunctionObj>
501 void assign_to(const reference_wrapper<FunctionObj>& f,
502 detail::function::function_obj_ref_tag)
504 if (!detail::function::has_empty_target(f.get_pointer())) {
506 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
508 R BOOST_FUNCTION_COMMA
509 BOOST_FUNCTION_TEMPLATE_ARGS
513 invoker = &actual_invoker_type::invoke;
514 this->manager = &detail::function::trivial_manager<FunctionObj>::get;
517 detail::function::make_any_pointer(
518 const_cast<FunctionObj*>(f.get_pointer())),
519 detail::function::clone_functor_tag);
523 template<typename FunctionObj>
524 void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
527 typename detail::function::
528 BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
530 R BOOST_FUNCTION_COMMA
531 BOOST_FUNCTION_TEMPLATE_ARGS
534 invoker = &actual_invoker_type::invoke;
535 this->manager = &detail::function::trivial_manager<FunctionObj>::get;
536 this->functor = detail::function::make_any_pointer(this);
539 typedef result_type (*invoker_type)(detail::function::any_pointer
541 BOOST_FUNCTION_TEMPLATE_ARGS);
543 invoker_type invoker;
546 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
548 inline void swap(BOOST_FUNCTION_FUNCTION<
549 R BOOST_FUNCTION_COMMA
550 BOOST_FUNCTION_TEMPLATE_ARGS ,
553 BOOST_FUNCTION_FUNCTION<
554 R BOOST_FUNCTION_COMMA
555 BOOST_FUNCTION_TEMPLATE_ARGS,
562 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
563 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
565 typename BOOST_FUNCTION_FUNCTION<
566 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
567 Allocator>::result_type
568 BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
571 ::operator()(BOOST_FUNCTION_PARMS) const
574 boost::throw_exception(bad_function_call());
576 return invoker(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
580 // Poison comparisons between boost::function objects of the same type.
581 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
583 void operator==(const BOOST_FUNCTION_FUNCTION<
584 R BOOST_FUNCTION_COMMA
585 BOOST_FUNCTION_TEMPLATE_ARGS ,
587 const BOOST_FUNCTION_FUNCTION<
588 R BOOST_FUNCTION_COMMA
589 BOOST_FUNCTION_TEMPLATE_ARGS ,
591 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
593 void operator!=(const BOOST_FUNCTION_FUNCTION<
594 R BOOST_FUNCTION_COMMA
595 BOOST_FUNCTION_TEMPLATE_ARGS ,
597 const BOOST_FUNCTION_FUNCTION<
598 R BOOST_FUNCTION_COMMA
599 BOOST_FUNCTION_TEMPLATE_ARGS ,
602 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
604 #if BOOST_FUNCTION_NUM_ARGS == 0
605 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
607 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
610 template<typename R BOOST_FUNCTION_COMMA
611 BOOST_FUNCTION_TEMPLATE_PARMS,
613 class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
614 : public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
615 BOOST_FUNCTION_COMMA Allocator>
617 typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
618 BOOST_FUNCTION_COMMA Allocator> base_type;
619 typedef function self_type;
621 struct clear_type {};
624 typedef typename base_type::allocator_type allocator_type;
626 function() : base_type() {}
628 template<typename Functor>
630 #ifndef BOOST_NO_SFINAE
631 ,typename enable_if_c<
632 (::boost::type_traits::ice_not<
633 (is_integral<Functor>::value)>::value),
641 #ifndef BOOST_NO_SFINAE
642 function(clear_type*) : base_type() {}
645 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
647 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
649 self_type& operator=(const self_type& f)
651 self_type(f).swap(*this);
655 template<typename Functor>
656 #ifndef BOOST_NO_SFINAE
657 typename enable_if_c<
658 (::boost::type_traits::ice_not<
659 (is_integral<Functor>::value)>::value),
666 self_type(f).swap(*this);
670 #ifndef BOOST_NO_SFINAE
671 self_type& operator=(clear_type*)
678 self_type& operator=(const base_type& f)
680 self_type(f).swap(*this);
685 #undef BOOST_FUNCTION_PARTIAL_SPEC
686 #endif // have partial specialization
688 } // end namespace boost
690 // Cleanup after ourselves...
691 #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
692 #undef BOOST_FUNCTION_COMMA
693 #undef BOOST_FUNCTION_FUNCTION
694 #undef BOOST_FUNCTION_FUNCTION_INVOKER
695 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
696 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
697 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
698 #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
699 #undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
700 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
701 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
702 #undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
703 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
704 #undef BOOST_FUNCTION_TEMPLATE_PARMS
705 #undef BOOST_FUNCTION_TEMPLATE_ARGS
706 #undef BOOST_FUNCTION_PARMS
707 #undef BOOST_FUNCTION_PARM
708 #undef BOOST_FUNCTION_ARGS
709 #undef BOOST_FUNCTION_ARG_TYPE
710 #undef BOOST_FUNCTION_ARG_TYPES
711 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
712 #undef BOOST_FUNCTION_RETURN