How do I expand a tuple into variadic template function's arguments?

前端 未结 13 1215
旧时难觅i
旧时难觅i 2020-11-22 07:49

Consider the case of a templated function with variadic template arguments:

template Tret func(const T&... t);
         


        
13条回答
  •  天涯浪人
    2020-11-22 08:33

    Here's my code if anyone is interested

    Basically at compile time the compiler will recursively unroll all arguments in various inclusive function calls -> calls -> calls ... -> calls <0> which is the last one and the compiler will optimize away the various intermediate function calls to only keep the last one which is the equivalent of func(arg1, arg2, arg3, ...)

    Provided are 2 versions, one for a function called on an object and the other for a static function.

    #include 
    
    /**
     * Object Function Tuple Argument Unpacking
     *
     * This recursive template unpacks the tuple parameters into
     * variadic template arguments until we reach the count of 0 where the function
     * is called with the correct parameters
     *
     * @tparam N Number of tuple arguments to unroll
     *
     * @ingroup g_util_tuple
     */
    template < uint N >
    struct apply_obj_func
    {
      template < typename T, typename... ArgsF, typename... ArgsT, typename... Args >
      static void applyTuple( T* pObj,
                              void (T::*f)( ArgsF... ),
                              const std::tr1::tuple& t,
                              Args... args )
      {
        apply_obj_func::applyTuple( pObj, f, t, std::tr1::get( t ), args... );
      }
    };
    
    //-----------------------------------------------------------------------------
    
    /**
     * Object Function Tuple Argument Unpacking End Point
     *
     * This recursive template unpacks the tuple parameters into
     * variadic template arguments until we reach the count of 0 where the function
     * is called with the correct parameters
     *
     * @ingroup g_util_tuple
     */
    template <>
    struct apply_obj_func<0>
    {
      template < typename T, typename... ArgsF, typename... ArgsT, typename... Args >
      static void applyTuple( T* pObj,
                              void (T::*f)( ArgsF... ),
                              const std::tr1::tuple& /* t */,
                              Args... args )
      {
        (pObj->*f)( args... );
      }
    };
    
    //-----------------------------------------------------------------------------
    
    /**
     * Object Function Call Forwarding Using Tuple Pack Parameters
     */
    // Actual apply function
    template < typename T, typename... ArgsF, typename... ArgsT >
    void applyTuple( T* pObj,
                     void (T::*f)( ArgsF... ),
                     std::tr1::tuple const& t )
    {
       apply_obj_func::applyTuple( pObj, f, t );
    }
    
    //-----------------------------------------------------------------------------
    
    /**
     * Static Function Tuple Argument Unpacking
     *
     * This recursive template unpacks the tuple parameters into
     * variadic template arguments until we reach the count of 0 where the function
     * is called with the correct parameters
     *
     * @tparam N Number of tuple arguments to unroll
     *
     * @ingroup g_util_tuple
     */
    template < uint N >
    struct apply_func
    {
      template < typename... ArgsF, typename... ArgsT, typename... Args >
      static void applyTuple( void (*f)( ArgsF... ),
                              const std::tr1::tuple& t,
                              Args... args )
      {
        apply_func::applyTuple( f, t, std::tr1::get( t ), args... );
      }
    };
    
    //-----------------------------------------------------------------------------
    
    /**
     * Static Function Tuple Argument Unpacking End Point
     *
     * This recursive template unpacks the tuple parameters into
     * variadic template arguments until we reach the count of 0 where the function
     * is called with the correct parameters
     *
     * @ingroup g_util_tuple
     */
    template <>
    struct apply_func<0>
    {
      template < typename... ArgsF, typename... ArgsT, typename... Args >
      static void applyTuple( void (*f)( ArgsF... ),
                              const std::tr1::tuple& /* t */,
                              Args... args )
      {
        f( args... );
      }
    };
    
    //-----------------------------------------------------------------------------
    
    /**
     * Static Function Call Forwarding Using Tuple Pack Parameters
     */
    // Actual apply function
    template < typename... ArgsF, typename... ArgsT >
    void applyTuple( void (*f)(ArgsF...),
                     std::tr1::tuple const& t )
    {
       apply_func::applyTuple( f, t );
    }
    
    // ***************************************
    // Usage
    // ***************************************
    
    template < typename T, typename... Args >
    class Message : public IMessage
    {
    
      typedef void (T::*F)( Args... args );
    
    public:
    
      Message( const std::string& name,
               T& obj,
               F pFunc,
               Args... args );
    
    private:
    
      virtual void doDispatch( );
    
      T*  pObj_;
      F   pFunc_;
      std::tr1::tuple args_;
    };
    
    //-----------------------------------------------------------------------------
    
    template < typename T, typename... Args >
    Message::Message( const std::string& name,
                                  T& obj,
                                  F pFunc,
                                  Args... args )
    : IMessage( name ),
      pObj_( &obj ),
      pFunc_( pFunc ),
      args_( std::forward(args)... )
    {
    
    }
    
    //-----------------------------------------------------------------------------
    
    template < typename T, typename... Args >
    void Message::doDispatch( )
    {
      try
      {
        applyTuple( pObj_, pFunc_, args_ );
      }
      catch ( std::exception& e )
      {
    
      }
    }
    

提交回复
热议问题