The void partial specialization of the function classes has been removed in

favor of a common interface. Regardless of the compiler's capabilities, the
result type of a Boost.Function function object that was declared void will
be "unused". This allows the result of a Boost.Function function object to
be passed as a parameter regardless of whether the function is declared as
returning void. It greatly simplifies the use of Boost.Function objects with
wrapper objects (i.e., when the side effects are important, but the result
isn't: consider binding and composition when calling a std::for_each loop)


[SVN r10491]
This commit is contained in:
Douglas Gregor
2001-07-01 02:17:36 +00:00
parent 53f9f4484f
commit 1f24873577
2 changed files with 7 additions and 320 deletions

View File

@ -103,13 +103,11 @@ namespace boost {
*/
template<typename T> struct function_return_type { typedef T type; };
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<>
struct function_return_type<void>
{
typedef unusable type;
};
#endif /* BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION */
// The operation type to perform on the given functor/function pointer
enum functor_manager_operation_type { clone_functor, destroy_functor };

View File

@ -125,7 +125,6 @@ namespace boost {
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
};
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<
typename FunctionPtr,
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
@ -155,7 +154,7 @@ namespace boost {
virtual unusable call(BOOST_FUNCTION_PARMS) const
{
function_ptr(BOOST_FUNCTION_ARGS);
return unusable;
return unusable();
}
virtual BOOST_FUNCTION_VOID_FUNCTION_INVOKER* clone() const
@ -212,91 +211,6 @@ namespace boost {
# 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
@ -386,7 +300,6 @@ namespace boost {
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
};
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<
typename FunctionObj,
# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
@ -479,97 +392,6 @@ namespace boost {
}
# 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,
@ -938,139 +760,6 @@ namespace boost {
}
};
#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 detail::function::BOOST_FUNCTION_BASE<void BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS,
Policy, Mixin, Allocator>
{
typedef detail::function::BOOST_FUNCTION_BASE<
void BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS,
Policy, Mixin, Allocator> base_type;
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;
#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
typedef typename base_type::impl_type impl_type;
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
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);
i->call(BOOST_FUNCTION_ARGS);
#else
this->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*>(this->impl);
i->call(BOOST_FUNCTION_ARGS);
#else
this->invoker(functor, true BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS
policy.postcall(this);
}
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);
}
};
#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<