Spacemoose
Spacemoose

Reputation: 4016

Determine the return-type of a function which is given as a templated-parameter

I have a function with a templated parameter which accepts another function. Within that function, I'd like to call a different template function which needs to be instantiated with the return-type of function argument.

Since I probably screwed that last paragraph up, let me attempt to clarify with an example:

template <typename funT>
void foo(funT function_to_call)
{
    auto data = bar<funT::return_value>();
    /// do some stuff with data.
    /// call function_to_call, but bar needed to be called first.
}

How do get funT::return_value ?

Many thanks,

Upvotes: 3

Views: 136

Answers (3)

Alejandro
Alejandro

Reputation: 3082

Apart from using result_of as others have suggested, you can also use decltype.

For the case where function_to_call accepts no parameters, you can do the following:

auto data = bar<decltype(function_to_call())>();

However, for a more generic case, as @101010 has pointed out, you can have your function accept any number of arguments. The resulting code would look like this:

template <typename funT, typename ...Args>
void foo(funT function_to_call, Args&&... args) 
{
   auto data = bar<decltype(function_to_call(std::forward<Args>(args)...))>();
}

For the cases that I've tried, decltype and std::result_of have the same functionality with regards to returning the correct type if the function type being passed in isn't a pointer-to-member, as @hvd pointed out. Looking looking through the g++ source, std::result_of is often implemented in terms of decltype for the case described above.

Using this seems much cleaner and more readable to me than the typename std::result_of<...>::type alternative, although the C++14 std::result_of_t option is quite attractive as well.

Upvotes: 1

Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42889

You could use type traits in particular std::result_of in the following manner:

template <typename funT>
void foo(funT function_to_call) {
  auto data = bar<typename std::result_of<decltype(function_to_call)&()>::type>();
  //...
}

LIVE DEMO

You could also further generalize to accept any kind of function along with its input arguments by using variadic templates in the following manner:

template <typename funT, typename ...Args>
void foo(funT function_to_call, Args... args) {
  auto data = bar<typename std::result_of<funT(Args...)>::type>();
  ...
}

LIVE DEMO

Upvotes: 1

rems4e
rems4e

Reputation: 3172

You can use typename std::result_of<funT()>::type to fit your needs, or std::result_of_t<funT()> if you have access to C++14.

Upvotes: 0

Related Questions