简体   繁体   中英

C++: compile-time checking for matching pairs of function calls?

I have a timer class I use to time blocks of code. Essentially something like this:

timer.start();
////do something
timer.end();

I am looking for a compile-time way to ensure that both the start and end call exist, and are within scope. Even hacky methods.

Here is one example of what I mean...this would generate a compile-time error if "end()" is called, but not "start()", due to the way a hidden variable "foo" is initialized.

#define start_macro bool foo = false; timer.start();
#define end_macro foo = true; timer.end();

//start_macro
////do something
end_macro //generates error because start_macro not called, thus foo not declared

But obviously the application of that method is limited because it generates no error if end() is the function not called.

Are there any clever ways I can ensure both functions are called, in order and in scope, at compile-time? I'm not interested in any run-time checking methods...I'd like a faster way to catch missing calls.

Unfortunaley there is no general solution. You would need to tell the compiler somehow, what are the matching functions. And, you never know, in which scope the closing function should be. So, rather difficult to impossible.

The better approach would be to use a wrapper class with constructor/destructor solution. The constructor would start the timer and the destrcutor would stop it. But that is runtime. . .

Another solution would be to write macro, which injects the code between timer start and stop, between such statements. But really not nice and anyway, marcros are not recommended. There could be also a template approach, trying to mimick that.

But for this to judge you need to specify more requirements.

You can use RAII, define a class wrapper, for example ScopedTimer , it's constructor calls start() and the destructor calls end() . Make your Timer::start() and Timer::end() protected, and make ScopedTimer as a friend of Timer , so that only ScopedTimer can calls to them.

There is no runtime checking. And there is no compile time checking either. It just makes it impossible to write code that calls one of the functions but not the other.

class  ScopedTimer {
 public:
  explicit ScopedTimer(Timer *tm)
      : tm_(tm)  {
    this->tm_->start();
  }
  ~ScopedTimer() { this->tm_->stop(); }
 protected:
  Timer* tm;
};

// Your code will be like this:
{ // This pair of braces defines the scope that you want to measure.
  ScopedTimer st(&timer);
  ////do something
}

Just as Shawn pointed out in his comment. To make sure timer has started, you simple put start of timer in constructor and stop in destructor. I used this method while making measurements for my project.

class Timer {
 public:
     Clock clock;
     Timer() { clock.start(); }
     ~Timer() 
     { 
         clock.stop(); 
         saveMeasurements(); 
     }
 private:
     void saveMeasurements(); //save measurements to file
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM