0

I try to pass a function as a parameter with a parameter pack as a second argument to a wrapper function.

In this simple case, the wrapper function should execute the passed function with the parameter in the pack, measure execution time and exit.

But I get the compile error with g++ 7.3.0 (c++14) on Ubuntu 18.04:

error: expression list treated as compound expression in functional cast [-fpermissive] 

for the line:

func(&args...);

The wrapper looks as follows:

template<typename func, typename ...Types>
void measure_time(func, Types... args)
{
    auto start = std::chrono::system_clock::now();

    // execute function here
    func(&args...);

    auto end = std::chrono::system_clock::now();
    std::cout << "Time for execution "
        << std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()
        << " microseconds\n";
}

I'm new to generic programming and parameter packs, but following the cpp reference for parameter packs this should work?

calling the measure_time function e.g. with a simple binary_search:

int binary_search(int *a, int v, int l, int r)
{
    while(r >= 1)
    {
        int m = (l+r)/2;
        if(v == a[m]) return m;
        if(v < a[m]) r = m-1; else l = m+1;
        if(l==m || r==m) break; 
    }
    return -1;
}

Produces the following instantiation (which seems correct to me) as source of error:

 In instantiation of ‘void measure_time(func, Types ...) [with func = int (*)(int*, int, int, int); Types = {int*, int, int, int}]’:

I found this article describing a compiler error, but I lack the knowledge to understand the situation and can't seem to deduct a workable solution if this is the case: temporary objects with variadic template arguments; another g++/clang++ difference

EDIT: Running the program with the -fpermissive flag and then executing the program works flawlessly.

Juri
  • 604
  • 9
  • 19

1 Answers1

1

It should be:

template<typename Func, typename ...Types>
void measure_time(Func func, Types&&... args)
{
    auto start = std::chrono::system_clock::now();

    // execute function here
    func(std::forward<Types>(args)...);

    auto end = std::chrono::system_clock::now();
    std::cout << "Time for execution "
        << std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()
        << " microseconds\n";
}

But even better would be to have your timing in a RAII class to allow to return value of your function easily.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Thanks! Going to look into this: [RAII](https://en.cppreference.com/w/cpp/language/raii) and this [Easily measure elapsed time](https://stackoverflow.com/questions/2808398/easily-measure-elapsed-time) – Juri Jan 09 '19 at 10:59
  • I also wasn't sure why we need std::forward. Where this resource helped [Advantages of using forward](https://stackoverflow.com/questions/3582001/advantages-of-using-forward) – Juri Jan 09 '19 at 11:06
  • `std::forward` allows to use function which use type such as `std::unique_ptr`, (or std::vector without copy). – Jarod42 Jan 09 '19 at 11:09