简体   繁体   English

C++:编译时检查匹配的 function 调用对?

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

I have a timer class I use to time blocks of code.我有一个计时器 class 我用来计时代码块。 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.我正在寻找一种编译时方法来确保开始和结束调用都存在,并且在 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.这是我的意思的一个例子......如果调用“end()”而不是“start()”,这将产生编译时错误,因为隐藏变量“foo”的初始化方式。

#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.但显然该方法的应用是有限的,因为如果 end() 是未调用的 function 则不会产生错误。

Are there any clever ways I can ensure both functions are called, in order and in scope, at compile-time?有没有什么聪明的方法可以确保在编译时按顺序和在 scope 中调用这两个函数? 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.而且,你永远不知道,scope 应该在哪个 function 结束。 So, rather difficult to impossible.所以,相当困难到不可能。

The better approach would be to use a wrapper class with constructor/destructor solution.更好的方法是使用带有构造函数/析构函数解决方案的包装器 class。 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() .您可以使用 RAII,定义一个 class 包装器,例如ScopedTimer ,它的构造函数调用start()和析构函数调用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.使您的Timer::start()Timer::end()受保护,并使ScopedTimer成为Timer的朋友,以便只有ScopedTimer可以调用它们。

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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