Create variadic template function to measure and e

2020-07-18 05:46发布

I am currently trying to implement a function that will take as input any other function and a valid set of input values for that function and return the result of the function as well as printing how long it took to execute it.

Here is what I have until now:

template<typename T, typename... Tail>

T measureAndExecute(const function<T(Tail...)> f, Tail... tail) {
    high_resolution_clock::time_point time1 = high_resolution_clock::now();
    T res = f(tail...);
    high_resolution_clock::time_point time2 = high_resolution_clock::now();
    auto duration = duration_cast<milliseconds>(time2 - time1).count();
    cout << duration << " milliseconds" << endl;
    return res;
}

And I try to run it with something like this:

int res = measureAndExecute(function<int(vector<int>&, vector<bool>&, unsigned long)> fibonacci, terms, calculated, n-1);

Which is a function to find a term in the Fibonacci series.

When I try to run it I get the following error:

error: expected '(' for function-style cast or type construction

Can somebody please give me a way forward or ideas on how to proceed?

2条回答
放荡不羁爱自由
2楼-- · 2020-07-18 06:03

I agree with @101010 that this is a unusual way of benchmarking a software.

That said, here is a solution that works also with functions havingvoid return type (the example in the question wouldn't have worked with them):

#include<type_traits>
#include<iostream>

struct Check {
    Check(): time1{std::chrono::high_resolution_clock::now()} {}

    ~Check() {
        std::chrono::high_resolution_clock::time_point time2 = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(time2 - time1).count();
        std::cout << duration << " milliseconds" << std::endl;
    }

    std::chrono::high_resolution_clock::time_point time1;
};


template<typename F, typename... Tail>
typename std::result_of<F(Tail&&...)>::type measureAndExecute(F f, Tail&&... tail) {  
    Check check;
    (void)check;
    return f(std::forward<Tail>(tail)...);
}

int f(int i) { return i; }
void g() { }

int main() {
    measureAndExecute(f, 42);
    measureAndExecute(g);
}

The basic idea is to create an instance of Check and exploit its lifetime to measure the time.

EDIT

As mentioned in the comments, a refinement of measureAndExecute would be:

template<typename F, typename... Tail>
typename std::result_of<F&&(Tail&&...)>::type measureAndExecute(F &&f, Tail&&... tail) {  
    Check check;
    (void)check;
    return std::forward<F>(f)(std::forward<Tail>(tail)...);
}
查看更多
倾城 Initia
3楼-- · 2020-07-18 06:08

This is a very naive way to do benchmarking. I suggest you take a look here for more advanced stuff. Nevertheless if you wanna stick to it you should change to:

template<typename F, typename... Tail>
auto measureAndExecute(F f, Tail&&... tail) -> typename std::result_of<F(Tail&&...)>::type {  
  std::chrono::high_resolution_clock::time_point time1 = std::chrono::high_resolution_clock::now();
  auto res = f(std::forward<Tail>(tail)...);
  std::chrono::high_resolution_clock::time_point time2 = std::chrono::high_resolution_clock::now();
  auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(time2 - time1).count();
  std::cout << duration << " milliseconds" << std::endl;
  return res;
}
查看更多
登录 后发表回答