Files
boost_function/include/boost/function/function_template.hpp
Beman Dawes 62db26b94d Initial comit
[SVN r10368]
2001-06-21 16:19:33 +00:00

1809 lines
60 KiB
C++

// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
/* Note: this header is a header template and must NOT have multiple-inclusion
protection. */
#include <cassert>
#include <algorithm>
namespace boost {
namespace detail {
namespace function {
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
struct BOOST_FUNCTION_INVOKER_BASE
{
virtual ~BOOST_FUNCTION_INVOKER_BASE() {}
virtual R call(BOOST_FUNCTION_PARMS) = 0;
virtual R call(BOOST_FUNCTION_PARMS) const = 0;
virtual BOOST_FUNCTION_INVOKER_BASE* clone() const = 0;
virtual void destroy(BOOST_FUNCTION_INVOKER_BASE*) = 0;
};
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
template<
typename FunctionPtr,
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename Allocator,
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_FUNCTION_INVOKER
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
: public BOOST_FUNCTION_INVOKER_BASE<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
{
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
explicit BOOST_FUNCTION_FUNCTION_INVOKER(FunctionPtr f) :
function_ptr(f) {}
virtual R call(BOOST_FUNCTION_PARMS)
{
return function_ptr(BOOST_FUNCTION_ARGS);
}
virtual R call(BOOST_FUNCTION_PARMS) const
{
return function_ptr(BOOST_FUNCTION_ARGS);
}
virtual BOOST_FUNCTION_FUNCTION_INVOKER* clone() const
{
# ifdef BOOST_NO_STD_ALLOCATOR
return new BOOST_FUNCTION_FUNCTION_INVOKER(function_ptr);
# else
typedef typename Allocator::
template rebind<BOOST_FUNCTION_FUNCTION_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, *this);
return static_cast<BOOST_FUNCTION_FUNCTION_INVOKER*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
}
virtual void destroy(BOOST_FUNCTION_INVOKER_BASE<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>* p)
{
# ifdef BOOST_NO_STD_ALLOCATOR
delete p;
# else
BOOST_FUNCTION_FUNCTION_INVOKER* victim =
dynamic_cast<BOOST_FUNCTION_FUNCTION_INVOKER*>(p);
typedef typename Allocator::
template rebind<BOOST_FUNCTION_FUNCTION_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
allocator.destroy(victim);
allocator.deallocate(victim, 1);
# endif // BOOST_NO_STD_ALLOCATOR
}
private:
FunctionPtr function_ptr;
#else
static R invoke(any_pointer function_ptr,
bool BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
return f(BOOST_FUNCTION_ARGS);
}
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
};
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<
typename FunctionPtr,
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename Allocator,
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
: public BOOST_FUNCTION_INVOKER_BASE<
unusable BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
{
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
explicit BOOST_FUNCTION_VOID_FUNCTION_INVOKER(FunctionPtr f) :
function_ptr(f) {}
virtual unusable call(BOOST_FUNCTION_PARMS)
{
function_ptr(BOOST_FUNCTION_ARGS);
return unusable();
}
virtual unusable call(BOOST_FUNCTION_PARMS) const
{
function_ptr(BOOST_FUNCTION_ARGS);
return unusable;
}
virtual BOOST_FUNCTION_VOID_FUNCTION_INVOKER* clone() const
{
# ifdef BOOST_NO_STD_ALLOCATOR
return new BOOST_FUNCTION_VOID_FUNCTION_INVOKER(function_ptr);
# else
typedef typename Allocator::
template rebind<BOOST_FUNCTION_VOID_FUNCTION_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, *this);
return static_cast<BOOST_FUNCTION_VOID_FUNCTION_INVOKER*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
}
virtual void destroy(BOOST_FUNCTION_INVOKER_BASE<
unusable BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>* p)
{
# ifdef BOOST_NO_STD_ALLOCATOR
delete p;
# else
BOOST_FUNCTION_VOID_FUNCTION_INVOKER* victim =
dynamic_cast<BOOST_FUNCTION_VOID_FUNCTION_INVOKER*>(p);
typedef typename Allocator::
template rebind<BOOST_FUNCTION_VOID_FUNCTION_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
allocator.destroy(victim);
allocator.deallocate(victim, 1);
# endif // BOOST_NO_STD_ALLOCATOR
}
private:
FunctionPtr function_ptr;
# else
static unusable invoke(any_pointer function_ptr,
bool BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
f(BOOST_FUNCTION_ARGS);
return unusable();
}
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
};
#else
template<
typename FunctionPtr,
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename Allocator,
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
: public BOOST_FUNCTION_INVOKER_BASE<
void BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
{
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
explicit BOOST_FUNCTION_VOID_FUNCTION_INVOKER(FunctionPtr f) :
function_ptr(f) {}
virtual void call(BOOST_FUNCTION_PARMS)
{
function_ptr(BOOST_FUNCTION_ARGS);
}
virtual void call(BOOST_FUNCTION_PARMS) const
{
function_ptr(BOOST_FUNCTION_ARGS);
}
virtual BOOST_FUNCTION_VOID_FUNCTION_INVOKER* clone() const
{
# ifdef BOOST_NO_STD_ALLOCATOR
return new BOOST_FUNCTION_VOID_FUNCTION_INVOKER(function_ptr);
# else
typedef typename Allocator::
template rebind<BOOST_FUNCTION_VOID_FUNCTION_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, *this);
return static_cast<BOOST_FUNCTION_VOID_FUNCTION_INVOKER *>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
}
virtual void destroy(BOOST_FUNCTION_INVOKER_BASE<
void BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>* p)
{
# ifdef BOOST_NO_STD_ALLOCATOR
delete p;
# else
BOOST_FUNCTION_VOID_FUNCTION_INVOKER* victim =
dynamic_cast<BOOST_FUNCTION_VOID_FUNCTION_INVOKER*>(p);
typedef typename Allocator::
template rebind<BOOST_FUNCTION_VOID_FUNCTION_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
allocator.destroy(victim);
allocator.deallocate(victim, 1);
# endif // BOOST_NO_STD_ALLOCATOR
}
private:
FunctionPtr function_ptr;
# else
static void invoke(any_pointer function_ptr,
bool BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
f(BOOST_FUNCTION_ARGS);
}
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<
typename FunctionObj,
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename Allocator,
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
: public BOOST_FUNCTION_INVOKER_BASE<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
{
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
explicit BOOST_FUNCTION_FUNCTION_OBJ_INVOKER(const FunctionObj& f) :
function_obj(f) {}
virtual R call(BOOST_FUNCTION_PARMS)
{
return function_obj(BOOST_FUNCTION_ARGS);
}
virtual R call(BOOST_FUNCTION_PARMS) const
{
return function_obj(BOOST_FUNCTION_ARGS);
}
virtual BOOST_FUNCTION_FUNCTION_OBJ_INVOKER* clone() const
{
#ifdef BOOST_NO_STD_ALLOCATOR
return new BOOST_FUNCTION_FUNCTION_OBJ_INVOKER(function_obj);
#else
typedef typename Allocator::
template rebind<BOOST_FUNCTION_FUNCTION_OBJ_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, *this);
return static_cast<BOOST_FUNCTION_FUNCTION_OBJ_INVOKER*>(copy);
#endif // BOOST_NO_STD_ALLOCATOR
}
virtual void destroy(BOOST_FUNCTION_INVOKER_BASE<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>* p)
{
#ifdef BOOST_NO_STD_ALLOCATOR
delete p;
#else
BOOST_FUNCTION_FUNCTION_OBJ_INVOKER* victim =
dynamic_cast<BOOST_FUNCTION_FUNCTION_OBJ_INVOKER*>(p);
typedef typename Allocator::
template rebind<BOOST_FUNCTION_FUNCTION_OBJ_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
allocator.destroy(victim);
allocator.deallocate(victim, 1);
#endif // BOOST_NO_STD_ALLOCATOR
}
private:
FunctionObj function_obj;
#else
static R invoke(any_pointer function_obj_ptr,
bool is_const BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionObj* f = static_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
if (is_const) {
const FunctionObj* fc = f;
return (*fc)(BOOST_FUNCTION_ARGS);
}
else {
return (*f)(BOOST_FUNCTION_ARGS);
}
}
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
};
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<
typename FunctionObj,
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename Allocator,
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
: public BOOST_FUNCTION_INVOKER_BASE<
unusable BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
{
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
explicit BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER(const FunctionObj& f)
: function_obj(f) {}
virtual unusable call(BOOST_FUNCTION_PARMS)
{
function_obj(BOOST_FUNCTION_ARGS);
return unusable();
}
virtual unusable call(BOOST_FUNCTION_PARMS) const
{
function_obj(BOOST_FUNCTION_ARGS);
return unusable();
}
virtual BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER* clone() const
{
#ifdef BOOST_NO_STD_ALLOCATOR
return new BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER(function_obj);
#else
typedef typename Allocator::
template rebind<BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, *this);
return static_cast<BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER*>(copy);
#endif // BOOST_NO_STD_ALLOCATOR
}
virtual void destroy(BOOST_FUNCTION_INVOKER_BASE<
unusable BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>* p)
{
#ifdef BOOST_NO_STD_ALLOCATOR
delete p;
#else
BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER* victim =
dynamic_cast<BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER*>(p);
typedef typename Allocator::
template rebind<BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
allocator.destroy(victim);
allocator.deallocate(victim, 1);
#endif // BOOST_NO_STD_ALLOCATOR
}
private:
FunctionObj function_obj;
# else
static unusable invoke(any_pointer function_obj_ptr,
bool is_const BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionObj* f = static_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
if (is_const) {
const FunctionObj* fc = f;
(*fc)(BOOST_FUNCTION_ARGS);
}
else {
(*f)(BOOST_FUNCTION_ARGS);
}
return unusable();
}
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
};
#else
template<
typename FunctionObj,
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename Allocator,
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
: public BOOST_FUNCTION_INVOKER_BASE<
void BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
{
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
explicit BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER(const FunctionObj& f)
: function_obj(f) {}
virtual void call(BOOST_FUNCTION_PARMS)
{
function_obj(BOOST_FUNCTION_ARGS);
}
virtual void call(BOOST_FUNCTION_PARMS) const
{
function_obj(BOOST_FUNCTION_ARGS);
}
virtual BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER * clone() const
{
# ifdef BOOST_NO_STD_ALLOCATOR
return new BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER (function_obj);
# else
typedef typename Allocator::
template rebind<BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
allocator.construct(copy, *this);
return static_cast<BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
}
virtual void destroy(BOOST_FUNCTION_INVOKER_BASE<
void BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>* p)
{
#ifdef BOOST_NO_STD_ALLOCATOR
delete p;
#else
BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER* victim =
dynamic_cast<BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER*>(p);
typedef typename Allocator::
template rebind<BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
allocator.destroy(victim);
allocator.deallocate(victim, 1);
#endif // BOOST_NO_STD_ALLOCATOR
}
private:
FunctionObj function_obj;
# else
static void
invoke(any_pointer function_obj_ptr,
bool is_const BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
FunctionObj* f = static_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
if (is_const) {
const FunctionObj* fc = f;
(*fc)(BOOST_FUNCTION_ARGS);
}
else {
(*f)(BOOST_FUNCTION_ARGS);
}
}
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
};
#endif
template<
typename FunctionPtr,
typename Allocator,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
{
typedef typename IF<(is_void<R>::value),
BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
FunctionPtr,
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
Allocator,
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>,
BOOST_FUNCTION_FUNCTION_INVOKER<
FunctionPtr,
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
Allocator,
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
>::type type;
};
template<
typename FunctionObj,
typename Allocator,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
{
typedef typename IF<(is_void<R>::value),
BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
FunctionObj,
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
Allocator,
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>,
BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
FunctionObj,
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
Allocator,
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
>::type type;
};
} // end namespace function
} // end namespace detail
template<
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS,
typename Policy = empty_function_policy,
typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base>
>
class BOOST_FUNCTION_FUNCTION : public function_base, public Mixin
{
public:
BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
typedef typename detail::function::function_return_type<R>::type
result_type;
typedef Policy policy_type;
typedef Mixin mixin_type;
typedef Allocator allocator_type;
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
private:
typedef detail::function::BOOST_FUNCTION_INVOKER_BASE<
result_type BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
impl_type;
public:
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
// Construct without a target
BOOST_FUNCTION_FUNCTION() : function_base() {}
#else
// Construct without a target
BOOST_FUNCTION_FUNCTION() : function_base()
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
, invoker(0)
# endif
{
}
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
#ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
// Clone the functor target f and make the clone the target
template<typename Functor>
BOOST_FUNCTION_FUNCTION(Functor BOOST_MSVC_INCLUDE(const &) f) :
function_base()
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
, invoker(0)
# endif
{
if (!detail::function::has_empty_target(f))
assign_to(f);
}
#else
template<typename Functor>
BOOST_FUNCTION_FUNCTION(const Functor& f) : function_base()
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
, invoker(0)
# endif
{
if (!detail::function::has_empty_target(&f)) {
typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
Functor,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<Functor, Allocator>::manage;
functor = manager(detail::function::any_pointer(const_cast<Functor*>(&f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
template<typename OtherR BOOST_FUNCTION_COMMA
BOOST_FUNCTION_OTHER_TEMPLATE_PARMS>
BOOST_FUNCTION_FUNCTION(OtherR (*f)(
BOOST_FUNCTION_OTHER_TEMPLATE_ARGS
)) : function_base()
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
, invoker(0)
# endif
{
if (f) {
typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS);
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<FunctionPtr, Allocator>
::manage;
functor = manager(detail::function::any_pointer(reinterpret_cast<void (*)()>(f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
#endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
// Clone the input BOOST_FUNCTION_FUNCTION's target
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f): function_base()
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
, invoker(0)
# endif
{
if (!f.empty()) {
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
impl_type* other_impl = reinterpret_cast<impl_type*>(f.impl);
impl = static_cast<void*>(other_impl->clone());
# else
invoker = f.invoker;
manager = f.manager;
functor = f.manager(f.functor, detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
// Destroy the target, if there is one
~BOOST_FUNCTION_FUNCTION() { clear(); }
void swap(BOOST_FUNCTION_FUNCTION& other)
{
#ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
std::swap(manager, other.manager);
std::swap(functor, other.functor);
std::swap(invoker, other.invoker);
#else
std::swap(impl, other.impl);
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
// Invoke the target
result_type operator()(BOOST_FUNCTION_PARMS)
{
assert(!this->empty());
policy_type policy;
policy.precall(this);
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
impl_type* i = reinterpret_cast<impl_type*>(impl);
result_type result = i->call(BOOST_FUNCTION_ARGS);
#else
result_type result = invoker(functor,
false BOOST_FUNCTION_COMMA
BOOST_FUNCTION_ARGS);
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
policy.postcall(this);
return result;
}
result_type operator()(BOOST_FUNCTION_PARMS) const
{
assert(!this->empty());
policy_type policy;
policy.precall(this);
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
const impl_type* i = reinterpret_cast<const impl_type*>(impl);
result_type result = i->call(BOOST_FUNCTION_ARGS);
#else
result_type result = invoker(functor,
true BOOST_FUNCTION_COMMA
BOOST_FUNCTION_ARGS);
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
policy.postcall(this);
return result;
}
// Clear out a target, if there is one
void clear()
{
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
if (impl) {
impl_type* i = reinterpret_cast<impl_type*>(impl);
i->destroy(i);
impl = 0;
}
#else
if (manager)
functor = manager(functor, detail::function::destroy_functor);
manager = 0;
invoker = 0;
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
#ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
// Assignment from any functor
template<typename Functor>
BOOST_FUNCTION_FUNCTION& operator=(Functor BOOST_MSVC_INCLUDE(const &) f)
{
clear();
if (!detail::function::has_empty_target(f)) {
// MSVC 6 eats the ';', so add another ';'. Don't ask me why.
assign_to(f);;
}
return *this;
}
#else
template<typename Functor>
BOOST_FUNCTION_FUNCTION& operator=(const Functor& f)
{
clear();
if (!detail::function::has_empty_target(&f)) {
typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
Functor,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<Functor, Allocator>::manage;
functor = manager(detail::function::any_pointer(const_cast<Functor*>(&f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
return *this;
}
template<typename OtherR BOOST_FUNCTION_COMMA
BOOST_FUNCTION_OTHER_TEMPLATE_PARMS>
BOOST_FUNCTION_FUNCTION&
operator=(OtherR (*f)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS))
{
clear();
if (f) {
typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS);
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
functor = manager(detail::function::any_pointer(reinterpret_cast<void (*)()>(f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
return *this;
}
#endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
#ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
// Assignment from any functor
template<typename Functor>
void set(Functor BOOST_MSVC_INCLUDE(const &) f)
{
clear();
if (!detail::function::has_empty_target(f)) {
// MSVC 6 eats the ';', so add another ';'. Don't ask me why.
assign_to(f);;
}
}
#else
template<typename Functor>
void set(const Functor& f)
{
clear();
if (!detail::function::has_empty_target(&f)) {
typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
Functor,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<Functor, Allocator>::manage;
functor = manager(detail::function::any_pointer(const_cast<Functor*>(&f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
template<typename OtherR BOOST_FUNCTION_COMMA
BOOST_FUNCTION_OTHER_TEMPLATE_PARMS>
void set(OtherR (*f)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS))
{
clear();
if (f) {
typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS);
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<FunctionPtr, Allocator>
::manage;
functor = manager(detail::function::any_pointer(reinterpret_cast<void (*)()>(f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
#endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
// Assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
{
clear();
if (!f.empty()) {
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
const impl_type* other_impl =
reinterpret_cast<const impl_type*>(f.impl);
impl = static_cast<void*>(other_impl->clone());
# else
invoker = f.invoker;
manager = f.manager;
functor = f.manager?
f.manager(f.functor, detail::function::clone_functor) : f.functor;
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
return *this;
}
// Assignment from another BOOST_FUNCTION_FUNCTION
void set(const BOOST_FUNCTION_FUNCTION& f)
{
clear();
if (!f.empty()) {
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
const impl_type* other_impl =
reinterpret_cast<const impl_type*>(f.impl);
impl = static_cast<void*>(other_impl->clone());
# else
invoker = f.invoker;
manager = f.manager;
functor = f.manager?
f.manager(f.functor, detail::function::clone_functor) : f.functor;
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
protected:
#if defined BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING || defined BOOST_NO_DEPENDENT_BASE_LOOKUP
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
// Clone a function pointer
template<typename FunctionPtr>
void* clone_functor(FunctionPtr f, detail::function::function_ptr_tag)
{
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
return static_cast<void*>(i);
}
// Clone a function object
template<typename FunctionObj>
void* clone_functor(FunctionObj& f, detail::function::function_obj_tag)
{
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
return static_cast<void*>(i);
}
# else
// Clone a function pointer
template<typename FunctionPtr>
detail::function::any_pointer
clone_functor(FunctionPtr f, detail::function::function_ptr_tag)
{
detail::function::any_pointer a(reinterpret_cast<void (*)()>(f));
return manager(a, detail::function::clone_functor);
}
// Clone a functor
template<typename FunctionObj>
detail::function::any_pointer
clone_functor(FunctionObj& f, detail::function::function_obj_tag)
{
detail::function::any_pointer a(static_cast<void*>(&f));
return manager(a, detail::function::clone_functor);
}
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
// Assign this BOOST_FUNCTION_FUNCTION to the given functor
template<typename Functor>
void assign_to(Functor f)
{
// Do we have a functor or a function pointer?
typedef typename detail::function::IF<
(is_pointer<Functor>::value),
detail::function::function_ptr_tag,
detail::function::function_obj_tag>::RET
target_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
impl = clone_functor(f, target_type());
# else
typedef typename detail::function::IF<(is_pointer<Functor>::value),
detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
Functor,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>,
detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
Functor,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
>::type
invoker_selector;
typedef typename invoker_selector::type invoker_type;
// Setup the new functor
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<Functor, Allocator>::manage;
functor = clone_functor(f, target_type());
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
#endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
#ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typedef result_type (*invoker_type)(detail::function::any_pointer,
bool BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
);
invoker_type invoker;
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
};
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<
BOOST_FUNCTION_TEMPLATE_PARMS BOOST_FUNCTION_COMMA
typename Policy,
typename Mixin,
typename Allocator
>
class BOOST_FUNCTION_FUNCTION<
void BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS,
Policy,
Mixin,
Allocator> : public function_base, public Mixin
{
public:
BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
typedef void result_type;
typedef void R;
typedef Policy policy_type;
typedef Mixin mixin_type;
typedef Allocator allocator_type;
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
private:
typedef detail::function::BOOST_FUNCTION_INVOKER_BASE<
result_type BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
impl_type;
public:
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
// Construct without a target
BOOST_FUNCTION_FUNCTION() : function_base() {}
#else
// Construct without a target
BOOST_FUNCTION_FUNCTION() : function_base()
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
, invoker(0)
# endif
{
}
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
#ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
// Clone the functor target f and make the clone the target
template<typename Functor>
BOOST_FUNCTION_FUNCTION(Functor BOOST_MSVC_INCLUDE(const &) f) :
function_base()
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
, invoker(0)
# endif
{
if (!detail::function::has_empty_target(f))
assign_to(f);
}
#else
template<typename Functor>
BOOST_FUNCTION_FUNCTION(const Functor& f) : function_base()
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
, invoker(0)
# endif
{
if (!detail::function::has_empty_target(&f)) {
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
Functor,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<Functor, Allocator>::manage;
functor = manager(detail::function::any_pointer(const_cast<Functor*>(&f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
template<typename OtherR BOOST_FUNCTION_COMMA
BOOST_FUNCTION_OTHER_TEMPLATE_PARMS>
BOOST_FUNCTION_FUNCTION(OtherR (*f)(
BOOST_FUNCTION_OTHER_TEMPLATE_ARGS
)) : function_base()
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
, invoker(0)
# endif
{
if (f) {
typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS);
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
functor = manager(detail::function::any_pointer(reinterpret_cast<void (*)()>(f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
#endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
// Clone the input BOOST_FUNCTION_FUNCTION's target
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f): function_base()
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
, invoker(0)
# endif
{
if (!f.empty()) {
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
impl_type* other_impl = reinterpret_cast<impl_type*>(f.impl);
impl = static_cast<void*>(other_impl->clone());
# else
invoker = f.invoker;
manager = f.manager;
functor = f.manager(f.functor, detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
// Destroy the target, if there is one
~BOOST_FUNCTION_FUNCTION() { clear(); }
void swap(BOOST_FUNCTION_FUNCTION& other)
{
# ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
std::swap(manager, other.manager);
std::swap(functor, other.functor);
std::swap(invoker, other.invoker);
# else
std::swap(impl, other.impl);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
// Invoke the target
result_type operator()(BOOST_FUNCTION_PARMS)
{
assert(!this->empty());
policy_type policy;
policy.precall(this);
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
impl_type* i = reinterpret_cast<impl_type*>(impl);
i->call(BOOST_FUNCTION_ARGS);
#else
invoker(functor, false BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
policy.postcall(this);
}
result_type operator()(BOOST_FUNCTION_PARMS) const
{
assert(!this->empty());
policy_type policy;
policy.precall(this);
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
const impl_type* i = reinterpret_cast<const impl_type*>(impl);
i->call(BOOST_FUNCTION_ARGS);
#else
invoker(functor, true BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
policy.postcall(this);
}
// Clear out a target, if there is one
void clear()
{
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
if (impl) {
impl_type* i = reinterpret_cast<impl_type*>(impl);
i->destroy(i);
impl = 0;
}
#else
if (manager)
functor = manager(functor, detail::function::destroy_functor);
manager = 0;
invoker = 0;
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
#ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
// Assignment from any functor
template<typename Functor>
BOOST_FUNCTION_FUNCTION& operator=(Functor BOOST_MSVC_INCLUDE(const &) f)
{
clear();
if (!detail::function::has_empty_target(f)) {
// MSVC 6 eats the ';', so add another ';'. Don't ask me why.
assign_to(f);;
}
return *this;
}
#else
template<typename Functor>
BOOST_FUNCTION_FUNCTION& operator=(const Functor& f)
{
clear();
if (!detail::function::has_empty_target(&f)) {
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
Functor,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<Functor, Allocator>::manage;
functor = manager(detail::function::any_pointer(const_cast<Functor*>(&f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
return *this;
}
template<typename OtherR BOOST_FUNCTION_COMMA
BOOST_FUNCTION_OTHER_TEMPLATE_PARMS>
BOOST_FUNCTION_FUNCTION&
operator=(OtherR (*f)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS))
{
clear();
if (f) {
typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS);
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
functor = manager(detail::function::any_pointer(reinterpret_cast<void (*)()>(f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
return *this;
}
#endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
#ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
// Assignment from any functor
template<typename Functor>
void set(Functor BOOST_MSVC_INCLUDE(const &) f)
{
clear();
if (!detail::function::has_empty_target(f)) {
// MSVC 6 eats the ';', so add another ';'. Don't ask me why.
assign_to(f);;
}
}
#else
template<typename Functor>
void set(const Functor& f)
{
clear();
if (!detail::function::has_empty_target(&f)) {
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
Functor,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<Functor, Allocator>::manage;
functor = manager(detail::function::any_pointer(const_cast<Functor*>(&f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
template<typename OtherR BOOST_FUNCTION_COMMA
BOOST_FUNCTION_OTHER_TEMPLATE_PARMS>
void set(OtherR (*f)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS))
{
clear();
if (f) {
typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS);
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
impl = static_cast<void*>(i);
# else
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
functor = manager(detail::function::any_pointer(reinterpret_cast<void (*)()>(f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
#endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
// Assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
{
clear();
if (!f.empty()) {
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
const impl_type* other_impl =
reinterpret_cast<const impl_type*>(f.impl);
impl = static_cast<void*>(other_impl->clone());
# else
invoker = f.invoker;
manager = f.manager;
functor = f.manager?
f.manager(f.functor, detail::function::clone_functor) : f.functor;
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
return *this;
}
// Assignment from another BOOST_FUNCTION_FUNCTION
void set(const BOOST_FUNCTION_FUNCTION& f)
{
clear();
if (!f.empty()) {
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
const impl_type* other_impl =
reinterpret_cast<const impl_type*>(f.impl);
impl = static_cast<void*>(other_impl->clone());
# else
invoker = f.invoker;
manager = f.manager;
functor = f.manager?
f.manager(f.functor, detail::function::clone_functor) : f.functor;
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
}
protected:
#if defined BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING || defined BOOST_NO_DEPENDENT_BASE_LOOKUP
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
// Clone a function pointer
template<typename FunctionPtr>
void* clone_functor(FunctionPtr f, detail::function::function_ptr_tag)
{
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
return static_cast<void*>(i);
}
// Clone a function object
template<typename FunctionObj>
void* clone_functor(FunctionObj& f, detail::function::function_obj_tag)
{
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
# ifdef BOOST_NO_STD_ALLOCATOR
impl_type* i = new invoker_type(f);
# else
typedef typename Allocator::template rebind<invoker_type>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
allocator_type allocator;
pointer_type copy = allocator.allocate(1);
new (copy) invoker_type(f);
impl_type* i = static_cast<impl_type*>(copy);
# endif // BOOST_NO_STD_ALLOCATOR
return static_cast<void*>(i);
}
# else
// Clone a function pointer
template<typename FunctionPtr>
detail::function::any_pointer clone_functor(FunctionPtr f, detail::function::function_ptr_tag)
{
detail::function::any_pointer a(reinterpret_cast<void (*)()>(f));
return manager(a, detail::function::clone_functor);
}
// Clone a functor
template<typename FunctionObj>
detail::function::any_pointer clone_functor(FunctionObj& f, detail::function::function_obj_tag)
{
detail::function::any_pointer a(static_cast<void*>(&f));
return manager(a, detail::function::clone_functor);
}
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
// Assign this BOOST_FUNCTION_FUNCTION to the given functor
template<typename Functor>
void assign_to(Functor f)
{
// Do we have a functor or a function pointer?
typedef typename detail::function::IF<(is_pointer<Functor>::value),
detail::function::function_ptr_tag,
detail::function::function_obj_tag>::RET
target_type;
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
impl = clone_functor(f, target_type());
# else
typedef typename detail::function::IF<(is_pointer<Functor>::value),
detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
Functor,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>,
detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
Functor,
Allocator,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
>::type
invoker_selector;
typedef typename invoker_selector::type invoker_type;
// Setup the new functor
invoker = &invoker_type::invoke;
manager = &detail::function::functor_manager<Functor, Allocator>::manage;
functor = clone_functor(f, target_type());
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}
#endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING
#ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typedef result_type (*invoker_type)(detail::function::any_pointer,
bool BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
);
invoker_type invoker;
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
typename Policy, typename Mixin, typename Allocator>
inline void swap(BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS ,
Policy,
Mixin,
Allocator
>& f1,
BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS,
Policy,
Mixin,
Allocator
>& f2)
{
f1.swap(f2);
}
}