我可以在编译时断言我的函数用户做了什么吗?

时间:2013-11-10 02:50:23

标签: c++

我正在构建一些库函数,其中一个基本上是一个带有任意键的计时器类。它在概念上看起来像这样:

template <typename Key>
class Timer
{
  void tic(Key key) {tics[key] = std::clock();
  void toc(Key key)
  {
    // calling this before tic has been called is fine
    if (!tic.find(key))
      tocs[key] = 0;
    else
      tocs[key] = std::clock() - tics[key];

    // BUT: writing code that calls "tocs" without ever calling "tics" should trigger
    // a compile-time error! How do I do this? Is it possible?
  }
  private:
  std::map<Key,clock_t> tics;
  std::map<Key,clock_t> tocs;
}

此课程的任务只是衡量每个键的tictoc次调用之间的时间。例如,在toc之前调用tic以允许班级在函数调用之间测量时间应该是完全合法的。但是,在代码的其他部分中调用tictoc而没有相应的toc / tic根本没有意义,所以它显然是编码错误 - 我想在编译时报告

所以,这应该没问题:

Timer<int> timer;

while (1)
{
  timer.toc(0);
  // this reports the time elapses between the while 
  // loop ending and the while loop starting
  timer.tic(1);
}

但是这些应该会产生编译时错误(好吧,警告会更合适):<​​/ p>

Timer<int> timer;

while (1)
{
  timer.toc(1); // this will always return 0
  timer.tic(0); // this is an unused initialization
}

有可能实现这一目标吗?我怀疑答案是 no ,但我想确定,因为它真的很整洁。

1 个答案:

答案 0 :(得分:0)

正如你在评论中喜欢这个命题,这是一个例子:

template<typename Key>
class Timer
{
 class CachePair
 {
  clock_t lastTimestamp, diff;

 public:
  CachePair() :
   lastTimestamp(0), diff(0)
  { }

  void update()
  {
   clock_t now = std::clock();
   diff = now - lastTimestamp;
   lastTimestamp = now;
  }
 };

 std::map<Key, CachePair> cache;

public:
 Timer()
 { }

 void tick(Key const& key)
 {
  cache[key].update();
 }

 clock_t const& value(Key const& key)
 {
  return cache[key].diff;
 }
};

没试过。如果您在CachePair上第一次调用update(Key)时使用C ++ 11来避免Key构造函数中的初始化,则可以改进这一点。

实际上你甚至可以消除第二个变量,如果大小那么并且也消除了很多并发症。

template<typename Key>
class Timer
{    
 std::map<Key, clock_t> cache;

public:
 Timer()
 { }

 clock_t tick(Key const& key)
 {
  clock_t& val = cache[key];

  clock_t now = std::clock();
  val = now; //this will update the value in map because it is defined as a reference to the variable in map
  return now - val;
 }
};

方式更简单吧,自然更好,因为有更简单的界面/更少的方法。您只需键入size_t timeElapsed = timer.tick(key);即可获得两次滴答之间的时间。