function.hpp:

- Use swap() for exception safe assignment operators

function_template.hpp:
	- Use swap() for exception safe assignment operators
	- Remove BOOST_FUNCTION_BASE class.
	- Support copying of mixins. (Richard Crossley)


[SVN r10614]
This commit is contained in:
Douglas Gregor
2001-07-14 18:41:19 +00:00
parent b51aa315da
commit 5754d88110
2 changed files with 205 additions and 222 deletions

View File

@ -468,7 +468,7 @@ namespace boost {
template<typename Functor> template<typename Functor>
function& operator=(const Functor& f) function& operator=(const Functor& f)
{ {
this->assign_to(f); function(f).swap(*this);
return *this; return *this;
} }
@ -476,45 +476,45 @@ namespace boost {
template<typename Functor> template<typename Functor>
function& operator=(Functor* f) function& operator=(Functor* f)
{ {
this->assign_to(f); function(f).swap(*this);
return *this; return *this;
} }
#endif // __BORLANDC__ #endif // __BORLANDC__
function& operator=(const base_type& f) function& operator=(const base_type& f)
{ {
this->assign_to_own(f); function(f).swap(*this);
return *this; return *this;
} }
function& operator=(const function& f) function& operator=(const function& f)
{ {
this->assign_to_own(f); function(f).swap(*this);
return *this; return *this;
} }
template<typename Functor> template<typename Functor>
void set(const Functor& f) void set(const Functor& f)
{ {
this->assign_to(f); function(f).swap(*this);
} }
#ifdef __BORLANDC__ #ifdef __BORLANDC__
template<typename Functor> template<typename Functor>
void set(Functor* f) void set(Functor* f)
{ {
this->assign_to(f); function(f).swap(*this);
} }
#endif // __BORLANDC__ #endif // __BORLANDC__
void set(const base_type& f) void set(const base_type& f)
{ {
this->assign_to_own(f); function(f).swap(*this);
} }
void set(const function& f) void set(const function& f)
{ {
this->assign_to_own(f); function(f).swap(*this);
} }
}; };

View File

@ -448,11 +448,9 @@ namespace boost {
> >
>::type type; >::type type;
}; };
} // end namespace function
} // end namespace detail
/* This base class encapsulates the copy behavior of the user-level
functionN classes. The void partial specialization used by compilers
that support partial specialization merely changes the call routines,
so we factor all other behavior here. */
template< template<
typename R BOOST_FUNCTION_COMMA typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS, BOOST_FUNCTION_TEMPLATE_PARMS,
@ -460,7 +458,7 @@ namespace boost {
typename Mixin = empty_function_mixin, typename Mixin = empty_function_mixin,
typename Allocator = std::allocator<function_base> typename Allocator = std::allocator<function_base>
> >
class BOOST_FUNCTION_BASE : public function_base, public Mixin class BOOST_FUNCTION_FUNCTION : public function_base, public Mixin
{ {
public: public:
BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
@ -471,27 +469,147 @@ namespace boost {
typedef T1 first_argument_type; typedef T1 first_argument_type;
typedef T2 second_argument_type; typedef T2 second_argument_type;
#endif #endif
typedef typename function_return_type<R>::type result_type; typedef typename detail::function::function_return_type<R>::type
result_type;
typedef Policy policy_type; typedef Policy policy_type;
typedef Mixin mixin_type; typedef Mixin mixin_type;
typedef Allocator allocator_type; typedef Allocator allocator_type;
private:
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typedef BOOST_FUNCTION_INVOKER_BASE< typedef detail::function::BOOST_FUNCTION_INVOKER_BASE<
result_type BOOST_FUNCTION_COMMA result_type BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS BOOST_FUNCTION_TEMPLATE_ARGS
> >
impl_type; impl_type;
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
// Construct without a target public:
BOOST_FUNCTION_BASE() : function_base() BOOST_FUNCTION_INIT {} explicit BOOST_FUNCTION_FUNCTION(const Mixin& m = Mixin()) :
function_base(), Mixin(m) BOOST_FUNCTION_INIT
// Destroy the target, if there is one
~BOOST_FUNCTION_BASE() { clear(); }
void swap(BOOST_FUNCTION_BASE& other)
{ {
}
template<typename Functor>
BOOST_FUNCTION_FUNCTION(const Functor& f, const Mixin& m = Mixin()) :
function_base(), Mixin(m) BOOST_FUNCTION_INIT
{
this->assign_to(f);
}
#ifdef __BORLANDC__
template<typename Functor>
BOOST_FUNCTION_FUNCTION(Functor* f, const Mixin& m = Mixin()) :
function_base(), Mixin(m) BOOST_FUNCTION_INIT
{
this->assign_to(f);
}
#endif // __BORLANDC__
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
function_base(), Mixin(static_cast<const Mixin&>(f))
BOOST_FUNCTION_INIT
{
this->assign_to_own(f);
}
~BOOST_FUNCTION_FUNCTION() { clear(); }
// 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;
}
template<typename Functor>
BOOST_FUNCTION_FUNCTION& operator=(const Functor& f)
{
BOOST_FUNCTION_FUNCTION(f).swap(*this);
return *this;
}
#ifdef __BORLANDC__
template<typename Functor>
BOOST_FUNCTION_FUNCTION& operator=(Functor* f)
{
BOOST_FUNCTION_FUNCTION(f).swap(*this);
return *this;
}
#endif // __BORLANDC__
template<typename Functor>
void set(const Functor& f)
{
BOOST_FUNCTION_FUNCTION(f).swap(*this);
}
#ifdef __BORLANDC__
template<typename Functor>
void set(Functor* f)
{
BOOST_FUNCTION_FUNCTION(f).swap(*this);
}
#endif // __BORLANDC__
// Assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
{
if (&f == this)
return *this;
BOOST_FUNCTION_FUNCTION(f).swap(*this);
return *this;
}
// Assignment from another BOOST_FUNCTION_FUNCTION
void set(const BOOST_FUNCTION_FUNCTION& f)
{
if (&f == this)
return;
BOOST_FUNCTION_FUNCTION(f).swap(*this);
}
void swap(BOOST_FUNCTION_FUNCTION& other)
{
if (&other == this)
return;
#ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
std::swap(manager, other.manager); std::swap(manager, other.manager);
std::swap(functor, other.functor); std::swap(functor, other.functor);
@ -499,6 +617,7 @@ namespace boost {
#else #else
std::swap(impl, other.impl); std::swap(impl, other.impl);
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
std::swap(static_cast<Mixin&>(*this),static_cast<Mixin&>(other));
} }
// Clear out a target, if there is one // Clear out a target, if there is one
@ -512,28 +631,24 @@ namespace boost {
} }
#else #else
if (manager) if (manager)
functor = manager(functor, destroy_functor); functor = manager(functor, detail::function::destroy_functor);
manager = 0; manager = 0;
invoker = 0; invoker = 0;
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
} }
protected:
void assign_to_own(const BOOST_FUNCTION_BASE& f) private:
void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
{ {
if (this == &f)
return;
this->clear();
if (!f.empty()) { if (!f.empty()) {
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
impl_type* other_impl = reinterpret_cast<impl_type*>(f.impl); impl_type* other_impl = reinterpret_cast<impl_type*>(f.impl);
this->impl = static_cast<void*>(other_impl->clone()); impl = static_cast<void*>(other_impl->clone());
# else # else
this->invoker = f.invoker; invoker = f.invoker;
this->manager = f.manager; manager = f.manager;
this->functor = f.manager(f.functor, clone_functor); functor = f.manager(f.functor, detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
} }
} }
@ -541,19 +656,19 @@ namespace boost {
template<typename Functor> template<typename Functor>
void assign_to(const Functor& f) void assign_to(const Functor& f)
{ {
typedef typename IF<(is_pointer<Functor>::value), typedef typename detail::function::IF<(is_pointer<Functor>::value),
function_ptr_tag, detail::function::function_ptr_tag,
function_obj_tag>::type tag; detail::function::function_obj_tag>::type tag;
this->assign_to(f, tag()); this->assign_to(f, tag());
} }
template<typename FunctionPtr> template<typename FunctionPtr>
void assign_to(FunctionPtr f, function_ptr_tag) void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
{ {
clear(); clear();
if (f) { if (f) {
typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr, FunctionPtr,
Allocator, Allocator,
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
@ -577,21 +692,22 @@ namespace boost {
impl = static_cast<void*>(i); impl = static_cast<void*>(i);
# else # else
invoker = &invoker_type::invoke; invoker = &invoker_type::invoke;
manager = &functor_manager<FunctionPtr, Allocator>::manage; manager = &detail::function::functor_manager<FunctionPtr,
functor = manager(any_pointer(reinterpret_cast<void (*)()>(f)), Allocator>::manage;
clone_functor); functor = manager(detail::function::any_pointer(
reinterpret_cast<void (*)()>(f)
),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
} }
} }
template<typename FunctionObj> template<typename FunctionObj>
void assign_to(const FunctionObj& f, function_obj_tag) void assign_to(const FunctionObj& f, detail::function::function_obj_tag)
{ {
clear(); if (!detail::function::has_empty_target(&f)) {
if (!has_empty_target(&f)) {
typedef typedef
typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj, FunctionObj,
Allocator, Allocator,
R BOOST_FUNCTION_COMMA R BOOST_FUNCTION_COMMA
@ -615,156 +731,23 @@ namespace boost {
impl = static_cast<void*>(i); impl = static_cast<void*>(i);
# else # else
invoker = &invoker_type::invoke; invoker = &invoker_type::invoke;
manager = &functor_manager<FunctionObj, Allocator>::manage; manager = &detail::function::functor_manager<FunctionObj,
functor = manager(any_pointer(const_cast<FunctionObj*>(&f)), Allocator>::manage;
clone_functor); functor =
manager(detail::function::any_pointer(const_cast<FunctionObj*>(&f)),
detail::function::clone_functor);
# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
} }
} }
#ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typedef result_type (*invoker_type)(any_pointer, typedef result_type (*invoker_type)(detail::function::any_pointer,
bool BOOST_FUNCTION_COMMA bool BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS); BOOST_FUNCTION_TEMPLATE_ARGS);
invoker_type invoker; invoker_type invoker;
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
}; };
} // 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 detail::function::BOOST_FUNCTION_BASE<R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS,
Policy, Mixin, Allocator>
{
typedef detail::function::BOOST_FUNCTION_BASE<
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS,
Policy, Mixin, Allocator> base_type;
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typedef typename base_type::impl_type impl_type;
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
public:
typedef typename base_type::result_type result_type;
typedef typename base_type::policy_type policy_type;
typedef typename base_type::mixin_type mixin_type;
typedef typename base_type::allocator_type allocator_type;
BOOST_FUNCTION_FUNCTION() : base_type() {}
template<typename Functor>
BOOST_FUNCTION_FUNCTION(const Functor& f) : base_type()
{
this->assign_to(f);
}
#ifdef __BORLANDC__
template<typename Functor>
BOOST_FUNCTION_FUNCTION(Functor* f) : base_type()
{
this->assign_to(f);
}
#endif // __BORLANDC__
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : base_type()
{
this->assign_to_own(f);
}
// 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*>(this->impl);
result_type result = i->call(BOOST_FUNCTION_ARGS);
#else
result_type result = this->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*>(this->impl);
result_type result = i->call(BOOST_FUNCTION_ARGS);
#else
result_type result = this->invoker(functor,
true BOOST_FUNCTION_COMMA
BOOST_FUNCTION_ARGS);
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
policy.postcall(this);
return result;
}
template<typename Functor>
BOOST_FUNCTION_FUNCTION& operator=(const Functor& f)
{
this->assign_to(f);
return *this;
}
#ifdef __BORLANDC__
template<typename Functor>
BOOST_FUNCTION_FUNCTION& operator=(Functor* f)
{
this->assign_to(f);
return *this;
}
#endif // __BORLANDC__
template<typename Functor>
void set(const Functor& f)
{
this->assign_to(f);
}
#ifdef __BORLANDC__
template<typename Functor>
void set(Functor* f)
{
this->assign_to(f);
}
#endif // __BORLANDC__
// Assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
{
this->assign_to_own(f);
return *this;
}
// Assignment from another BOOST_FUNCTION_FUNCTION
void set(const BOOST_FUNCTION_FUNCTION& f)
{
this->assign_to_own(f);
}
};
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS , template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
typename Policy, typename Mixin, typename Allocator> typename Policy, typename Mixin, typename Allocator>