AlexD
AlexD

Reputation: 325

Templated return type inferred from type of forwarded function

I am attempting to write a header file containing a function that calls a function within main.cpp, forwarding an arbitrary number of parameters. The return type of this code needs to match the return type of the forwarded function. In an attempt to achieve this, I wrote the following dummy program, but I am unable to get this to compile. I would be grateful for some help:

#include <functional>
#include <iostream>

double f(double x, int params) {
    return 1;
}

template <typename func, typename... Args>
double test(std::function<func(double, Args...)> predicate, Args&&... params){
    return 2;
}

int main() {
    int dummy = 1;
    double result = test(&f, dummy);
    std::cout<<result<<std::endl;
    return 0;
}

The compiler (clang++-3.8) gives the following error:

test.cpp:15:18: error: no matching function for call to 'test'
        double result = test(&f, dummy);
                    ^~~~
test.cpp:9:8: note: candidate template ignored: could not match
      'function<type-parameter-0-0 (double, type-parameter-0-1...)>'  against
      'double (*)(double, int)'
double test(std::function<func(double, Args...)> predicate, Args&&... params){
       ^
1 error generated.

Upvotes: 4

Views: 190

Answers (1)

Kerrek SB
Kerrek SB

Reputation: 476950

How about this:

#include <utility>

template <typename F, typename ...Args>
auto test(F&& f, Args&&... args)
    -> decltype(std::forward<F>(f)(std::forward<Args>(args)...)) {
  return std::forward<F>(f)(std::forward<Args>(args)...);
}

Usage:

test(f, j, dummy);

In C++14 you can write this more simply as:

template <typename F, typename ...Args>
decltype(auto) test(F&& f, Args&&... args) {
  return std::forward<F>(f)(std::forward<Args>(args)...);
}

Upvotes: 3

Related Questions