First of all, I feel like this must have been asked already somewhere, but all my searches proved fruitless. If this is indeed a duplicate of something somewhere, I apologize in advance.

I am trying to mass-benchmark a bunch of functions from OpenCV and to do so I wanted to write a small meta-function that takes the function to run, its parameters (which vary according to the function passed) and essentially sets up the timing and runs the function in a loop.

Since I'm planning to pass lambdas to the meta-function as well later on (to benchmark composition of functions), I thought of using `std::function`.

This is the code I came up with after reading [the parameter pack description](https://en.cppreference.com/w/cpp/language/parameter_pack):

```
template<typename ...Ts> 
void run_test(std::string test_name, int num_repeats, std::function<void(Ts...)> f, Ts... fargs)
{
    std::cout << std::endl << "Starting " << test_name << std::endl;
    start_timing(test_name);
    for(int i=0; i<num_repeats; i++)
    {
        f(fargs...);
    }
    end_timing(num_repeats);
}

```

As you see, functionality is down to a minimum. `start_timing` and `end_timing` are simple helper functions beyond the scope of this question.

In my main, I call:

```
// im_in defined and loaded elsewhere
cv::Mat out(im_in.size(), CV_8U);
run_test(
    "erode 3x3",
    100,
    cv::erode,
    im_in, out, cv::Mat::ones(3,3,CV_8U)
);

```

Now, if I try to compile this, I get:

```
error: no matching function for call to 'run_test(const char [10], const int&, void (&)(cv::InputArray, cv::OutputArray, cv::InputArray, cv::Point, int, int, const Scalar&), cv::Mat&, cv::Mat&, cv::MatExpr)'
  );
  ^
note: candidate: template<class ... Ts> void run_test(std::__cxx11::string, int, std::function<void(Ts ...)>, Ts ...)
 void run_test(std::string test_name, int num_repeats, std::function<void(Ts...)> f, Ts... fargs)
      ^~~~~~~~
note:   template argument deduction/substitution failed:
note:   mismatched types 'std::function<void(Ts ...)>' and 'void (*)(cv::InputArray, cv::OutputArray, cv::InputArray, cv::Point, int, int, const Scalar&) {aka void (*)(const cv::_InputArray&, const cv::_OutputArray&, const cv::_InputArray&, cv::Point_<int>, int, int, const cv::Scalar_<double>&)}'
  );

```

So... what am I doing wrong? Why is it having a type mismatch instead of deducing the types in `Ts...` from the parameters list as I expected?

---

### Update:

After writing the last question above, I realized it might have problems deducing `Ts...` for the `std::function` because the parameter comes before the actual parameter list to expand into `Ts...`. So, I changed my code as follows (essentialy, I moved the `f` parameter at the end):

```
void run_test(std::string test_name, int num_repeats, Ts... fargs, std::function<void(Ts...)> f)
{ ... }

```

Of course, I also adapted the function call accordingly:

```
cv::Mat out(im_in.size(), CV_8U);
run_test(
    "erode 3x3",
    NUM_REPEATS,
    im_in, out, cv::Mat::ones(3,3,CV_8U),
    cv::erode, // <<<<<<<<<<<<<<<<<<<<<<<
);

```

Now, if I compile, I get a different error:

```
error: expected primary-expression before ')' token );

```

The change in error makes me think the order of the parameters was indeed important. Is, however, this the correct one? If so, what am I doing wrong?

---

### Update2:

Writing the first update, it struck me that probably my assumption that `f` can take a function and convert it to a `std::function` was probably wrong. After a quick research, it seems it is.

I tried replacing `std::function<void(Ts...)> f` with both `auto f` and `auto& f` (& compiling with C++14 enabled), but the `expected primary-expression` error is still there.

For all I could research, I couldn't find a way that allows me to just pass the function relying on the compiler to figure out the types.
I'm thinking of adapting C++17's `std::apply` function implementation shown [here](http://en.cppreference.com/w/cpp/utility/apply) adding my timing loop around the `invoke` call, but I don't understand that code, so the chance of getting something wrong is high.