Get input/output type of callable

2019-07-08 10:38发布

问题:

I have the following problem:

template<typename Func, typename T_in = /*input type of Func */, typename T_out = /*output type of Func */>
std::vector<T_out> foo( Func f, 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;
}


int main()
{
  // example for f(x) = x*x
  std::vector<float> input = { /* ... */ };
  auto res = foo( [](float in){ return in*in; }, input );

  return 0;
}

As you can see above, I try to implement a function foo which 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 foo (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.

回答1:

The type T_in can be deduced from the input vector.

I think that the deduction of T_out is a work for std::result_of_t

template <typename Func, typename T_in,
          typename T_out = std::result_of_t<Func(T_in)>>
std::vector<T_out> foo( Func f, 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;
}

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.



回答2:

decltype would work for this, along with changing foo's return type to auto.

template<typename Func, typename T_in>
auto foo( Func f, const std::vector<T_in>& input)
{
  std::vector<decltype(f(input[0]))> res( input.size() );

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

  return res;
}


int main()
{
  // example for f(x) = x*x
  std::vector<float> input = { /* ... */ };
  auto res = foo( [](float in){ return in*in; }, input );

  return 0;
}


回答3:

Using a map of functions it actually very common design pattern is c++. i recommend you using std::Map container for this. here is a link.

good luck :)