
Tobias Schwinger wrote:
João Abecasis wrote:
1 - support for function pointers was completely broken. Specifically, I learned that result_of doesn't handle cv-qualified function pointers.
<snip>
3 - Function references weren't handled at all.
Taking the function argument by value (just like the STL) could help. ...which might be why result_of doesn't address the cases you describe.
We can still optimize the forwarding from unpack_args to unpack_args_impl and the client can optimize the forwarding to unpack_args by explicitly specifying the first template argument (see attached code). Regards, Tobias #include <boost/mpl/eval_if.hpp> #include <boost/mpl/identity.hpp> #include <boost/type_traits/is_class.hpp> #include <boost/type_traits/add_reference.hpp> namespace boost { namespace somewhere { namespace utility { template<typename F> struct forward_functor : mpl::eval_if< is_class<F>, add_reference<F>, mpl::identity<F> > { }; } namespace detail { template <typename F> struct func_acceptor_impl { static void accept_func(F f); // take f by whatever F is }; } template <typename F> void accept_func(F f) // take f by value { detail::func_acceptor_impl< typename utility::forward_functor<F>::type >::accept_func(f); } //---- template<typename F> void performance_critical_algorithm(F f) // client that uses the forward_functor metafunction and a non-deduced // template argument to reduce copying { for (; /* often */ ;) accept_func< typename utility::forward_functor<F>::type > (f); } struct a_class { }; void test() // instantiates templates { accept_func( static_cast< void(&)() > ( test) ); accept_func( test ); accept_func( static_cast< void(*)() > (& test) ); accept_func( & test ); accept_func( a_class() ); performance_critical_algorithm( static_cast< void(&)() > ( test) ); performance_critical_algorithm( test ); performance_critical_algorithm( static_cast< void(*)() > (& test) ); performance_critical_algorithm( & test ); performance_critical_algorithm( a_class() ); } } }