From 8cbd121969a4b98e0652a65614f57f49ff420777 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 3 Dec 2001 16:28:33 +0000 Subject: [PATCH] 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] --- include/boost/function/function_base.hpp | 51 +++++++++++++++++++- include/boost/function/function_template.hpp | 22 +++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/include/boost/function/function_base.hpp b/include/boost/function/function_base.hpp index e439f54..bca9269 100644 --- a/include/boost/function/function_base.hpp +++ b/include/boost/function/function_base.hpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace boost { namespace detail { @@ -70,6 +71,37 @@ namespace boost { typedef typename select::template Result::type type; }; + // Determine if the incoming argument is a reference_wrapper +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct is_ref + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + + template + struct is_ref > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +#else // no partial specialization + typedef char yes_type; + typedef double no_type; + + no_type is_ref_tester(...); + + template + yes_type is_ref_tester(reference_wrapper*); + + template + 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 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::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::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(0)); + } + /** * The functor_manager class contains a static function "manage" which * can clone or destroy the given function/function object pointer. diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index e0dae22..676a6ec 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -391,6 +391,28 @@ namespace boost { } } + template + void assign_to(const reference_wrapper& 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(&f.get())), + detail::function::clone_functor_tag); + } + } + typedef result_type (*invoker_type)(detail::function::any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS);