fast_mem_fn.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 249 行

HPP
249
字号
// (C) Copyright Tobias Schwinger//// Use modification and distribution are subject to the boost Software License,// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt).//------------------------------------------------------------------------------//// This example implements a very efficient, generic member function wrapper.////// Detailed description// ====================//// For most platforms C++ runs on (maybe all hardware platforms, as opposed to// virtual machines) there are indirect calls that take more time to execute // than direct ones. Further calling a function usually takes more time than // inlining it at the call site.//// A direct call is a machine instruction that calls a subroutine at a known// address encoded in the instruction itself. C++ compilers usually emit one of// these instructions for each function call to a nonvirtual function (a call to// a virtual function requires either two direct calls or one indirect call).// An indirect call is a machine instruction that calls a subroutine at an // address known at runtime. C++ compilers usually emit at least one of these // instructions for a call through a callable builtin variable.//// It is possible to use callable scalars as non-type template arguments. This// way the compiler knows which function we want to call when generating the// code for the call site, so it may inline (if it decides to do so) or use a // direct call instead of being forced to use a slow, indirect call.//// We define a functor class template that encodes the function to call in its// type via a non-type template argument. Its (inline declared) overloaded // function call operator calls the function through that non-type template // argument. In the best case we end up inlining the callee directly at the// point of the call.//// Decomposition of the wrapped member function's type is needed in order to // implement argument forwarding (just using a templated call operator we would // encounter what is known as "the forwarding problem" [Dimov1]). Further we// can eliminate unecessary copies for each by-value parameter by using a // reference to its const qualified type for the corresponding parameter of the// wrapper's function call operator.//// Finally we provide a macro that does have similar semantics to the function // template mem_fn of the Bind [2] library.// We can't use a function template and use a macro instead, because we use a// member function pointer that is a compile time constant. So we first have to// deduce the type and create a template that accepts this type as a non-type // template argument, which is passed in in a second step. The macro hides this// lengthy expression from the user.////// Limitations// ===========//// The "this-argument" must be specified as a reference.////// Bibliography// ============//// [Dimov1] Dimov, P., Hinnant H., Abrahams, D. The Forwarding Problem//          http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm//// [Dimov2] Dimov, P. Documentation of boost::mem_fn//          http://www.boost.org/libs/bind/mem_fn.html#ifndef BOOST_EXAMPLE_FAST_MEM_FN_HPP_INCLUDED#ifndef BOOST_PP_IS_ITERATING#include <boost/function_types/result_type.hpp>#include <boost/function_types/function_arity.hpp>#include <boost/function_types/parameter_types.hpp>#include <boost/function_types/is_member_function_pointer.hpp>#include <boost/mpl/transform_view.hpp>#include <boost/mpl/begin.hpp>#include <boost/mpl/next.hpp>#include <boost/mpl/deref.hpp>#include <boost/utility/enable_if.hpp>#include "detail/param_type.hpp"namespace example{  namespace ft = boost::function_types;  namespace mpl = boost::mpl;  using namespace mpl::placeholders;  // the functor class template  template< typename MFPT, MFPT MemberFunction    , size_t Arity = ::example::ft::function_arity<MFPT>::value  >  struct fast_mem_fn;  // ------- ---- --- -- - - - -  // deduce type and capture compile time value   #define BOOST_EXAMPLE_FAST_MEM_FN(mfp) \      ::example::make_fast_mem_fn(mfp).make_fast_mem_fn<mfp>()  template<typename MFPT>  struct fast_mem_fn_maker  {    template<MFPT Callee>    fast_mem_fn<MFPT,Callee> make_fast_mem_fn()    {      return fast_mem_fn<MFPT,Callee>();    }   };  template<typename MFPT>      typename boost::enable_if<boost::is_member_function_pointer<MFPT>,   fast_mem_fn_maker<MFPT>                                                >::type  make_fast_mem_fn(MFPT)  {    return fast_mem_fn_maker<MFPT>();  }  // ------- ---- --- -- - - - -  namespace detail  {    // by-value forwarding optimization    template<typename T>    struct parameter_types      : mpl::transform_view<ft::parameter_types<T>,param_type<_> >    { };   }  // ------- ---- --- -- - - - -  template< typename MFPT, MFPT MemberFunction >  struct fast_mem_fn<MFPT, MemberFunction, 1>  {    // decompose the result and the parameter types (public for introspection)    typedef typename ft::result_type<MFPT>::type result_type;    typedef detail::parameter_types<MFPT> parameter_types;  private:    // iterate the parameter types     typedef typename mpl::begin<parameter_types>::type i0;  public:     // forwarding function call operator    result_type operator()( typename mpl::deref<i0>::type a0) const    {      return (a0.*MemberFunction)();    };  };  template< typename MFPT, MFPT MemberFunction >  struct fast_mem_fn<MFPT, MemberFunction, 2>  {    // decompose the result and the parameter types (public for introspection)    typedef typename ft::result_type<MFPT>::type result_type;    typedef detail::parameter_types<MFPT> parameter_types;  private:    // iterate the parameter types     typedef typename mpl::begin<parameter_types>::type i0;    typedef typename mpl::next<i0>::type i1;  public:     // forwarding function call operator    result_type operator()( typename mpl::deref<i0>::type a0                          , typename mpl::deref<i1>::type a1) const    {      return (a0.*MemberFunction)(a1);    };  };  template< typename MFPT, MFPT MemberFunction >  struct fast_mem_fn<MFPT, MemberFunction, 3>  {    // decompose the result and the parameter types (public for introspection)    typedef typename ft::result_type<MFPT>::type result_type;    typedef detail::parameter_types<MFPT> parameter_types;  private:    // iterate the parameter types     typedef typename mpl::begin<parameter_types>::type i0;    typedef typename mpl::next<i0>::type i1;    typedef typename mpl::next<i1>::type i2;  public:     // forwarding function call operator    result_type operator()( typename mpl::deref<i0>::type a0                          , typename mpl::deref<i1>::type a1                          , typename mpl::deref<i2>::type a2) const    {      return (a0.*MemberFunction)(a1,a2);    };  };  // ...}// ------- ---- --- -- - - - -// preprocessor-based code generator to continue the repetitive part, above#include <boost/preprocessor/cat.hpp>#include <boost/preprocessor/arithmetic/inc.hpp>#include <boost/preprocessor/iteration/iterate.hpp>#include <boost/preprocessor/iteration/local.hpp>#include <boost/preprocessor/repetition/enum_shifted_params.hpp>#include <boost/preprocessor/repetition/enum_binary_params.hpp>namespace example{  #if BOOST_FT_MAX_ARITY >= 4  #   define  BOOST_PP_FILENAME_1 "fast_mem_fn.hpp"  #   define  BOOST_PP_ITERATION_LIMITS (4,BOOST_FT_MAX_ARITY)  #   include BOOST_PP_ITERATE()  #endif}#define BOOST_EXAMPLE_FAST_MEM_FN_HPP_INCLUDED#else  #define N BOOST_PP_FRAME_ITERATION(1)  template< typename MFPT, MFPT MemberFunction >  struct fast_mem_fn<MFPT, MemberFunction, N >  {    // decompose the result and the parameter types (public for introspection)    typedef typename ft::result_type<MFPT>::type result_type;    typedef detail::parameter_types<MFPT> parameter_types;  private:    // iterate the parameter types     typedef typename mpl::begin<parameter_types>::type i0;    #define  BOOST_PP_LOCAL_LIMITS (0,N-2)    #define  BOOST_PP_LOCAL_MACRO(j) \    typedef typename mpl::next< i ## j >::type BOOST_PP_CAT(i,BOOST_PP_INC(j)) ;    #include BOOST_PP_LOCAL_ITERATE()  public:     // forwarding function call operator    result_type operator()(         BOOST_PP_ENUM_BINARY_PARAMS(N, typename mpl::deref<i,>::type a) )  const    {      return (a0.*MemberFunction)(BOOST_PP_ENUM_SHIFTED_PARAMS(N,a));    };  };  #undef N#endif#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?