Home > Back-end >  How to use void parameter when using template in C
How to use void parameter when using template in C

Time:05-26

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 ?

  •  Tags:  
  • c
  • Related