I want to make a function to test the running time of the incoming function. I use templates to make it applicable to many functions.
I omitted the code for counting time. like this:
template<typename F>
void get_run_time(F func)
{
//time start
func;
//time end
}
But if a function I pass in is void, an error will be report and prompt me to add F=void.
I tried to add it, but it didn't work. I can change void to bool, but it's very strange.
Another problem is that I want to test a function time and run my whole code normally .So I increased the return value. like this:
template<typename F>
F get_run_time(F func)
{
//time start
F tf=func;
//time end
return tf;
}
But the actual test time is obviously wrong. I guess it starts to run the function when it return .How can it get the running results before continuing with the following code?
The idiomatic C++ way (as I see it) is this
template <class F>
auto call(F f)
{
Timer t;
return f();
}
This works with functions returning void. Note, no start and stop here. Timer is a RAII class that starts the timer on construction and stops on destruction.
Forwarding parameters to f and niceties like std::invoke are not shown for brevity.
First, you need to call the passed function to actually time its execution. Note, in your code you do not call it, using the () call operator:
template <typename Func>
void timer1 (Func func)
{
// start timer
func();
// stop timer
}
Second, note these nuances:
// Will take the same time as the timer1
template <typename Func>
Func timer2 (Func func1)
{
// func2 is a copy of func1
// This copying won't increase the time as you thought it will
Func func2 = func1;
// You still need to call the function
func2();
// Returns pointer to function
return func2;
}
void foo() { std::cout << "foo()" << std::endl; }
int main() {
// Func, here, is a type void (*)()
// Prints "foo()"
timer2(foo);
}
Third, you may want to look toward this approach:
// Since C++14
auto timer3 = [](auto&& func, auto&&... args)
{
// start timer
// Forward the func and invoke the call operator
// with however many forwarded arguments passed to the timer3
std::forward<decltype(func)>(func)(std::forward<decltype(args)>(args)...);
// stop timer
};
void foo(int, int) {}
int main()
{
timer3(foo, 21, 42);
}
Even more proper and concise way to do the job, as noted by the @JHBonarius, is to use the std::invoke (since C++17), which was covered in this thread: What is std::invoke in C++?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With