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?
CodePudding user response:
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.
CodePudding user response:
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 ?