Search code examples
c++c++14callabletemplate-argument-deduction

Get input/output type of callable within a class definition


I have the following problem:

template< typename Func >
class A
{
  public:
    A( Func f ) : _f( f ) {}

    // ...

    template< typename T_in = /*input type of _f */, typename T_out = /*output type of _f */ >
    std::vector<T_out> operator()( const std::vector<T_in>& input)
    {
      std::vector<T_out> res( input.size() );

      for( size_t i = 0 ; i < input.size() ; ++i )
        res[ i ] = _f( input[ i ] );

      return res;
    }

  private:
    Func _f;
    // ...

};

template< typename Func >
A<Func> A_wrapper( Func f )
{
  return A<Func>( f );
}

int main()
{
  // example for f(x) = x*x
  std::vector<float> input = { /* ... */ };

  auto f          = []( float in ){ return in*in; };
  auto map_square = A_wrapper( f );

  auto res = map_square( input );

  return 0;
}

As you can see above, I try to implement a class A whose function operator() maps a function _f to each element of an input vector input.

My problem is the following: I want the elements of the input vector input to have the input type of _f (i.e., T_in) and the elements of the output vector the output type of _f (i.e., T_out) but without passing the input/output type of _f explicitly to the class A, the function A_wrapper which I use for type deduction and/or the function operator() (due to a better readability of the code). Has anyone an idea how the input/output type of _f can be deduced automatically at compile time?

Many thanks in advance.

BTW: The question here is related to my previous post Get input/output type of callable


Solution

  • Same question, same answer: you can deduce T_in from the input vector and T_out using std::result_of_t

    #include <vector>
    #include <functional>
    
    template< typename Func >
    class A
    {
      public:
        A( Func f ) : _f( f ) {}
    
        // ...
    
        template< typename T_in,
                  typename T_out = std::result_of_t<Func(T_in)>>
        std::vector<T_out> operator()( const std::vector<T_in> & input)
        {
          std::vector<T_out> res( input.size() );
    
          for( size_t i = 0 ; i < input.size() ; ++i )
            res[ i ] = _f( input[ i ] );
    
          return res;
        }
    
      private:
        Func _f;
        // ...
    
    };
    
    template< typename Func >
    A<Func> A_wrapper( Func f )
    {
      return A<Func>( f );
    }
    
    int main()
    {
      // example for f(x) = x*x
      std::vector<float> input = { /* ... */ };
    
      auto f          = []( float in ){ return in*in; };
      auto map_square = A_wrapper( f );
    
      auto res = map_square( input );
    
      return 0;
     }
    

    Using typename std::result_of<Func(T_in)>::type instead of std::result_of_t<Func(T_in)> should work also for C++11, not only for C++14.