function_base.hpp:

- Add trivial_manager that does nothing but copy object pointers
  - Add is_ref to determine if a type is a reference_wrapper
  - Add function_obj_ref_tag for reference_wrappers
  - Teach get_function_tag about reference_wrappers

function_template.hpp:
  - Add assign_to overload for reference_wrappers (these don't throw)


[SVN r11875]
This commit is contained in:
Douglas Gregor
2001-12-03 16:28:33 +00:00
parent 2e67e2126b
commit 8cbd121969
2 changed files with 71 additions and 2 deletions

View File

@ -23,6 +23,7 @@
#include <typeinfo>
#include <boost/config.hpp>
#include <boost/type_traits.hpp>
#include <boost/ref.hpp>
namespace boost {
namespace detail {
@ -70,6 +71,37 @@ namespace boost {
typedef typename select::template Result<Then,Else>::type type;
};
// Determine if the incoming argument is a reference_wrapper
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
struct is_ref
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<typename T>
struct is_ref<reference_wrapper<T> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
#else // no partial specialization
typedef char yes_type;
typedef double no_type;
no_type is_ref_tester(...);
template<typename T>
yes_type is_ref_tester(reference_wrapper<T>*);
template<typename T>
struct is_ref
{
static T* t;
BOOST_STATIC_CONSTANT(bool,
value = (sizeof(is_ref_tester(t)) == sizeof(yes_type)));
};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
/**
* A union of a function pointer and a void pointer. This is necessary
* because 5.2.10/6 allows reinterpret_cast<> to safely cast between
@ -122,6 +154,7 @@ namespace boost {
struct function_ptr_tag {};
struct function_obj_tag {};
struct member_ptr_tag {};
struct function_obj_ref_tag {};
template<typename F>
class get_function_tag
@ -130,12 +163,26 @@ namespace boost {
function_ptr_tag,
function_obj_tag>::type ptr_or_obj_tag;
public:
typedef typename IF<(is_member_pointer<F>::value),
member_ptr_tag,
ptr_or_obj_tag>::type type;
ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
public:
typedef typename IF<(is_ref<F>::value),
function_obj_ref_tag,
ptr_or_obj_or_mem_tag>::type type;
};
// The trivial manager does nothing but return the same pointer (if we
// are cloning) or return the null pointer (if we are deleting).
any_pointer trivial_manager(any_pointer f,
functor_manager_operation_type op)
{
if (op == clone_functor_tag)
return f;
else
return any_pointer(reinterpret_cast<void*>(0));
}
/**
* The functor_manager class contains a static function "manage" which
* can clone or destroy the given function/function object pointer.

View File

@ -391,6 +391,28 @@ namespace boost {
}
}
template<typename FunctionObj>
void assign_to(const reference_wrapper<FunctionObj>& f,
detail::function::function_obj_ref_tag)
{
if (!detail::function::has_empty_target(&f.get())) {
typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
invoker = &invoker_type::invoke;
manager = &detail::function::trivial_manager;
functor =
manager(detail::function::any_pointer(
const_cast<FunctionObj*>(&f.get())),
detail::function::clone_functor_tag);
}
}
typedef result_type (*invoker_type)(detail::function::any_pointer
BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS);