C++: 如何在编译时检查函数调用匹配的一对?

3

我有一个计时器类,用于计算代码块的执行时间。基本上是这样的:

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

我正在寻找一种编译时的方法,以确保开始调用和结束调用都存在并处于范围内。即使是hacky的方法也可以。

这里有一个例子... 由于隐藏变量“foo”的初始化方式,如果没有调用“start()”而调用“end()”,则会生成编译时错误。

#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

但是显然,如果未调用 end() 函数,该方法的应用是有限的,因为它不会产生错误。

是否有任何聪明的方法可以在编译时确保两个函数按顺序且在范围内被调用? 我不感兴趣运行时检查的方法……我希望有一种更快的方法来捕获缺少的调用。


2
使用RAII - 一个在构造时启动计时器并在销毁时结束计时器的对象。然后在与您正在计时的任何内容相同的块中包含该类型的对象。与lock_guard等标准类的想法相同。 - Shawn
3个回答

3
很遗憾,没有通用的解决方案。您需要以某种方式告诉编译器哪些函数相匹配。而且,您永远不知道关闭函数应该在哪个范围内。因此,这相当困难,甚至是不可能的。
更好的方法是使用具有构造函数/析构函数解决方案的包装类。构造函数将启动计时器,而析构函数将停止它。但这是运行时的...
另一种解决方案是编写宏,在这些语句之间注入代码。但这真的不太好,而且宏也不推荐使用。还可以尝试使用模板方法来模拟。
但要判断这一点,您需要指定更多的要求。

3
你可以使用RAII技术,定义一个类的包装器例如ScopedTimer,它的构造函数调用start(),析构函数调用end()。将Timer::start()Timer::end()保护起来,并将ScopedTimer设置为Timer的友元,以便只有ScopedTimer才能调用它们。
这种方法没有运行时检查,也没有编译时检查,但它使得编写只调用其中一个函数的代码变得不可能。
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
}


0
正如Shawn在评论中指出的那样。为确保计时器已启动,您只需在构造函数中设置计时器的开始,并在析构函数中停止计时器。我在制作项目测量时使用了这种方法。
class Timer {
 public:
     Clock clock;
     Timer() { clock.start(); }
     ~Timer() 
     { 
         clock.stop(); 
         saveMeasurements(); 
     }
 private:
     void saveMeasurements(); //save measurements to file
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接