对于事件反应器和前摄器中的超时,我使用优先级队列,它还允许 O(log(n)) 随机访问删除事件(当事件发出信号/完成而不是发生超时时)。我存储std::pair<std::chrono::steady_clock::time_point, Timed *>
whereTimed
是一个添加了一个索引(指向队列)的类,以便在调用TimedQ::Remove(Timed *p)
. 当我想要一个与超时关联的事件类型时,我从Timed
. 队列的Top()
并Pop()
返回一对。
我曾经有一堆使用队列的代码,例如
std::tie(timePt0, eventPtr0) = timeoutQ.Pop();
std::tie(timePt1, eventPtr1) = std::move(hold);
Timed *
在我开始在队列中使用基类而不是特定事件类型(即Timed
最初是模板类型)之前,它工作得很好,因为我最终需要支持可以与超时相关联的多种不同事件类型。但是,eventPtr*
由于是派生类型(我可以static_cast
从Timed *
队列返回的 a 中获取),上述代码不再有效。
我想知道最好的方法是什么。现在,它最终变得非常冗长,我也担心创建临时工等效率:
auto v(timeoutQ.Pop());
timePt0 = v.first;
eventPtr0 = static_cast<TimedEvent *>(v.second);
std::tie(timePt1, eventPtr1) = std::move(std::make_pair(hold.first, static_cast<TimedEvent *>(hold.second)); // I didn't literally do it like this, but I'm just trying to illustrate my struggle
我唯一的另一个想法是对派生事件类返回一对的函数进行模板化,但从代码大小的角度来看,这似乎很糟糕,因为即使机器代码应该相同,也会创建这些函数的多个实例,因为在所有情况下,它都是一个存储的指针。
编辑: 我也尝试过使用它,它可以编译,但我不确定它是否正确或有效:
template<class D>
std::pair<std::chrono::steady_clock::time_point, D *> &&Cnvrt(std::pair<std::chrono::steady_clock::time_point, Timed *> &&in)
{
return std::make_pair(in.first, static_cast<D *>(in.second));
}
最初的例子会变成
std::tie(timePt0, eventPtr0) = Cnvrt<std::remove_pointer<decltype(eventPtr0)>::type>(timeoutQ.Pop());
std::tie(timePt1, eventPtr1) = Cnvrt<std::remove_pointer<decltype(eventPtr1)>::type>(hold);