// Boost.Function library
-// Copyright Douglas Gregor 2001-2006. Use, modification and
-// distribution is subject to the Boost Software License, Version
-// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// Copyright Douglas Gregor 2001-2006
+// Copyright Emil Dotchevski 2007
+// Use, modification and distribution is subject to the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// For more information, see http://www.boost.org
// protection.
#include <boost/function/detail/prologue.hpp>
+#if defined(BOOST_MSVC)
+# pragma warning( push )
+# pragma warning( disable : 4127 ) // "conditional expression is constant"
+#endif
+
#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
#define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
#define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
-// Type of the default allocator
-#ifndef BOOST_NO_STD_ALLOCATOR
-# define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
-#else
-# define BOOST_FUNCTION_DEFAULT_ALLOCATOR int
-#endif // BOOST_NO_STD_ALLOCATOR
-
// Comma if nonzero number of arguments
#if BOOST_FUNCTION_NUM_ARGS == 0
# define BOOST_FUNCTION_COMMA
# define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
#endif
-#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable: 4127) // conditional expression is constant.
-#endif
-
-#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable: 4127) // conditional expression is constant.
-#endif
-
namespace boost {
namespace detail {
namespace function {
/**
* vtable for a specific boost::function instance.
*/
- template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
+ template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
struct BOOST_FUNCTION_VTABLE : vtable_base
{
#ifndef BOOST_NO_VOID_RETURNS
{
init(f);
}
+ template<typename F,typename Allocator>
+ BOOST_FUNCTION_VTABLE(F f, Allocator) : vtable_base(), invoker(0)
+ {
+ init_a<Allocator>(f);
+ }
template<typename F>
bool assign_to(F f, function_buffer& functor)
typedef typename get_function_tag<F>::type tag;
return assign_to(f, functor, tag());
}
+ template<typename F,typename Allocator>
+ bool assign_to_a(F f, function_buffer& functor, Allocator a)
+ {
+ typedef typename get_function_tag<F>::type tag;
+ return assign_to_a(f, functor, a, tag());
+ }
void clear(function_buffer& functor)
{
typedef typename get_function_tag<F>::type tag;
init(f, tag());
}
+ template<typename Allocator,typename F>
+ void init_a(F f)
+ {
+ typedef typename get_function_tag<F>::type tag;
+ init_a<Allocator>(f, tag());
+ }
// Function pointers
template<typename FunctionPtr>
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
- manager = &functor_manager<FunctionPtr, Allocator>::manage;
+ manager = &functor_manager<FunctionPtr>::manage;
+ }
+ template<typename Allocator,typename FunctionPtr>
+ void init_a(FunctionPtr f, function_ptr_tag)
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
+ FunctionPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ actual_invoker_type;
+
+ invoker = &actual_invoker_type::invoke;
+ manager = &functor_manager_a<FunctionPtr, Allocator>::manage;
}
template<typename FunctionPtr>
return false;
}
}
+ template<typename FunctionPtr,typename Allocator>
+ bool
+ assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag)
+ {
+ return assign_to(f,functor,function_ptr_tag());
+ }
// Member pointers
#if BOOST_FUNCTION_NUM_ARGS > 0
// right target_type() values.
this->init(mem_fn(f));
}
+ template<typename Allocator,typename MemberPtr>
+ void init_a(MemberPtr f, member_ptr_tag)
+ {
+ // DPG TBD: Add explicit support for member function
+ // objects, so we invoke through mem_fn() but we retain the
+ // right target_type() values.
+ this->init_a<Allocator>(mem_fn(f));
+ }
template<typename MemberPtr>
bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag)
return false;
}
}
+ template<typename MemberPtr,typename Allocator>
+ bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag)
+ {
+ // DPG TBD: Add explicit support for member function
+ // objects, so we invoke through mem_fn() but we retain the
+ // right target_type() values.
+ if (f) {
+ this->assign_to_a(mem_fn(f), functor, a);
+ return true;
+ } else {
+ return false;
+ }
+ }
#endif // BOOST_FUNCTION_NUM_ARGS > 0
// Function objects
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
- manager = &functor_manager<FunctionObj, Allocator>::manage;
+ manager = &functor_manager<FunctionObj>::manage;
+ }
+ template<typename Allocator,typename FunctionObj>
+ void init_a(FunctionObj /*f*/, function_obj_tag)
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
+ FunctionObj,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ actual_invoker_type;
+
+ invoker = &actual_invoker_type::invoke;
+ manager = &functor_manager_a<FunctionObj, Allocator>::manage;
}
// Assign to a function object using the small object optimization
{
new ((void*)&functor.data) FunctionObj(f);
}
+ template<typename FunctionObj,typename Allocator>
+ void
+ assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_)
+ {
+ assign_functor(f,functor,mpl::true_());
+ }
// Assign to a function object allocated on the heap.
template<typename FunctionObj>
void
assign_functor(FunctionObj f, function_buffer& functor, mpl::false_)
{
-#ifndef BOOST_NO_STD_ALLOCATOR
- typedef typename Allocator::template rebind<FunctionObj>::other
- allocator_type;
- typedef typename allocator_type::pointer pointer_type;
-
- allocator_type allocator;
- pointer_type copy = allocator.allocate(1);
- allocator.construct(copy, f);
-
- // Get back to the original pointer type
- functor.obj_ptr = static_cast<FunctionObj*>(copy);
-# else
functor.obj_ptr = new FunctionObj(f);
-# endif // BOOST_NO_STD_ALLOCATOR
+ }
+ template<typename FunctionObj,typename Allocator>
+ void
+ assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_)
+ {
+ typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
+ typedef typename Allocator::template rebind<functor_wrapper_type>::other
+ wrapper_allocator_type;
+ typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
+ wrapper_allocator_type wrapper_allocator(a);
+ wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
+ wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
+ functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
+ functor.obj_ptr = new_f;
}
template<typename FunctionObj>
return false;
}
}
+ template<typename FunctionObj,typename Allocator>
+ bool
+ assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag)
+ {
+ if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
+ assign_functor_a(f, functor, a,
+ mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
+ return true;
+ } else {
+ return false;
+ }
+ }
// Reference to a function object
template<typename FunctionObj>
invoker = &actual_invoker_type::invoke;
manager = &reference_manager<FunctionObj>::get;
}
+ template<typename Allocator,typename FunctionObj>
+ void
+ init_a(const reference_wrapper<FunctionObj>& f, function_obj_ref_tag)
+ {
+ init(f,function_obj_ref_tag());
+ }
template<typename FunctionObj>
bool
return false;
}
}
+ template<typename FunctionObj,typename Allocator>
+ bool
+ assign_to_a(const reference_wrapper<FunctionObj>& f,
+ function_buffer& functor, Allocator, function_obj_ref_tag)
+ {
+ return assign_to(f,functor,function_obj_ref_tag());
+ }
public:
invoker_type invoker;
template<
typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
+ BOOST_FUNCTION_TEMPLATE_PARMS
>
class BOOST_FUNCTION_FUNCTION : public function_base
+
+#if BOOST_FUNCTION_NUM_ARGS == 1
+
+ , public std::unary_function<T0,R>
+
+#elif BOOST_FUNCTION_NUM_ARGS == 2
+
+ , public std::binary_function<T0,T1,R>
+
+#endif
+
{
public:
#ifndef BOOST_NO_VOID_RETURNS
private:
typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
- R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Allocator>
+ R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
vtable_type;
struct clear_type {};
BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
BOOST_FUNCTION_ARG_TYPES
- typedef Allocator allocator_type;
typedef BOOST_FUNCTION_FUNCTION self_type;
BOOST_FUNCTION_FUNCTION() : function_base() { }
{
this->assign_to(f);
}
+ template<typename Functor,typename Allocator>
+ BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
+#ifndef BOOST_NO_SFINAE
+ ,typename enable_if_c<
+ (boost::type_traits::ice_not<
+ (is_integral<Functor>::value)>::value),
+ int>::type = 0
+#endif // BOOST_NO_SFINAE
+ ) :
+ function_base()
+ {
+ this->assign_to_a(f,a);
+ }
#ifndef BOOST_NO_SFINAE
BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
}
return *this;
}
+ template<typename Functor,typename Allocator>
+ void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
+ {
+ this->clear();
+ try {
+ this->assign_to_a(f,a);
+ } catch (...) {
+ vtable = 0;
+ throw;
+ }
+ }
#ifndef BOOST_NO_SFINAE
BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
else vtable = 0;
}
+ template<typename Functor,typename Allocator>
+ void assign_to_a(Functor f,Allocator a)
+ {
+ static vtable_type stored_vtable(f,a);
+ if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
+ else vtable = 0;
+ }
};
- template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
- typename Allocator>
+ template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
inline void swap(BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS ,
- Allocator
+ BOOST_FUNCTION_TEMPLATE_ARGS
>& f1,
BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS,
- Allocator
+ BOOST_FUNCTION_TEMPLATE_ARGS
>& f2)
{
f1.swap(f2);
}
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
- template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
+ template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
typename BOOST_FUNCTION_FUNCTION<
- R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
- Allocator>::result_type
- BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
-
- Allocator>
+ R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type
+ BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
::operator()(BOOST_FUNCTION_PARMS) const
{
if (this->empty())
#endif
// Poison comparisons between boost::function objects of the same type.
-template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
- typename Allocator>
+template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
void operator==(const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS ,
- Allocator>&,
+ BOOST_FUNCTION_TEMPLATE_ARGS>&,
const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS ,
- Allocator>&);
-template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
- typename Allocator>
+ BOOST_FUNCTION_TEMPLATE_ARGS>&);
+template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
void operator!=(const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS ,
- Allocator>&,
+ BOOST_FUNCTION_TEMPLATE_ARGS>&,
const BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS ,
- Allocator>&);
+ BOOST_FUNCTION_TEMPLATE_ARGS>& );
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
#endif
template<typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
-class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
- : public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
- BOOST_FUNCTION_COMMA Allocator>
+ BOOST_FUNCTION_TEMPLATE_PARMS>
+class function<BOOST_FUNCTION_PARTIAL_SPEC>
+ : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
{
- typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
- BOOST_FUNCTION_COMMA Allocator> base_type;
+ typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
typedef function self_type;
struct clear_type {};
public:
- typedef typename base_type::allocator_type allocator_type;
function() : base_type() {}
base_type(f)
{
}
+ template<typename Functor,typename Allocator>
+ function(Functor f, Allocator a
+#ifndef BOOST_NO_SFINAE
+ ,typename enable_if_c<
+ (boost::type_traits::ice_not<
+ (is_integral<Functor>::value)>::value),
+ int>::type = 0
+#endif
+ ) :
+ base_type(f,a)
+ {
+ }
#ifndef BOOST_NO_SFINAE
function(clear_type*) : base_type() {}
}
};
-#ifdef BOOST_MSVC
-# pragma warning(pop)
-#endif
-
#undef BOOST_FUNCTION_PARTIAL_SPEC
#endif // have partial specialization
} // end namespace boost
-#ifdef BOOST_MSVC
-# pragma warning(pop)
-#endif
-
// Cleanup after ourselves...
#undef BOOST_FUNCTION_VTABLE
-#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
#undef BOOST_FUNCTION_COMMA
#undef BOOST_FUNCTION_FUNCTION
#undef BOOST_FUNCTION_FUNCTION_INVOKER
#undef BOOST_FUNCTION_ARG_TYPES
#undef BOOST_FUNCTION_VOID_RETURN_TYPE
#undef BOOST_FUNCTION_RETURN
+
+#if defined(BOOST_MSVC)
+# pragma warning( pop )
+#endif