diff --git a/include/boost/function/function_base.hpp b/include/boost/function/function_base.hpp index 3e77568..1542512 100644 --- a/include/boost/function/function_base.hpp +++ b/include/boost/function/function_base.hpp @@ -77,37 +77,6 @@ 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 @@ -161,6 +130,7 @@ namespace boost { struct function_obj_tag {}; struct member_ptr_tag {}; struct function_obj_ref_tag {}; + struct stateless_function_obj_tag {}; template class get_function_tag @@ -172,10 +142,15 @@ namespace boost { typedef typename IF<(is_member_pointer::value), member_ptr_tag, ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag; - public: - typedef typename IF<(is_ref::value), + + typedef typename IF<(is_reference_wrapper::value), function_obj_ref_tag, - ptr_or_obj_or_mem_tag>::type type; + ptr_or_obj_or_mem_tag>::type or_ref_tag; + + public: + typedef typename IF<(is_stateless::value), + stateless_function_obj_tag, + or_ref_tag>::type type; }; // The trivial manager does nothing but return the same pointer (if we diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index 521e2d1..07ffae1 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -50,10 +50,16 @@ BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \ BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER \ + BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \ + BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \ + BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) namespace boost { namespace detail { @@ -124,6 +130,37 @@ namespace boost { } }; + template< + typename FunctionObj, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER + { + static R invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) + { + FunctionObj f; + return f(BOOST_FUNCTION_ARGS); + } + }; + + template< + typename FunctionObj, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER + { + static unusable invoke(any_pointer BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + + { + FunctionObj f; + f(BOOST_FUNCTION_ARGS); + return unusable(); + } + }; + template< typename FunctionPtr, typename R BOOST_FUNCTION_COMMA @@ -165,6 +202,28 @@ namespace boost { > >::type type; }; + + template< + typename FunctionObj, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER + { + typedef typename IF<(is_void::value), + BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >, + BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + > + >::type type; + }; + } // end namespace function } // end namespace detail @@ -390,6 +449,22 @@ namespace boost { } } + template + void assign_to(FunctionObj f, detail::function::stateless_function_obj_tag) + { + typedef + typename detail::function:: + BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + invoker_type; + invoker = &invoker_type::invoke; + function_base::manager = &detail::function::trivial_manager; + function_base::functor = detail::function::any_pointer(this); + } + typedef result_type (*invoker_type)(detail::function::any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS); @@ -428,7 +503,10 @@ namespace boost { #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER +#undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER +#undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER +#undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER