我正在构建一些库函数,其中一个基本上是一个带有任意键的计时器类。它在概念上看起来像这样:
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;
}
此课程的任务只是衡量每个键的tic
和toc
次调用之间的时间。例如,在toc
之前调用tic
以允许班级在函数调用之间测量时间应该是完全合法的。但是,在代码的其他部分中调用tic
或toc
而没有相应的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 ,但我想确定,因为它真的很整洁。
答案 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);
即可获得两次滴答之间的时间。