【发布时间】:2017-06-09 21:32:53
【问题描述】:
我正在考虑 C 中 void* 的一个用例,我试图以最惯用的方式将该代码翻译成 C++,而不会降低效率。这是问题所在,以下是解决方法
void callback(void* args) {
Something* something = static_cast<Something*>(args);
// use something
}
Something something;
add_callback(callback, &something);
这里,只要参数 something 发生某些事件,就会调用回调。在 C++ 中进行此操作的惯用方式(如果您认为不正确,请帮助我找到更好的解决方案)类似于 关注
Something something;
add_callback([=something]() {
// do something
});
然后add_callback() 将在内部擦除 lambda 的类型并将其存储在 std::function<> 中,以便在时机成熟时回调。与旧版本相比,这样做的好处是回调更好地封装了它的状态。
但是我看到的问题是,每次调用回调时,这都会导致虚函数调度的不必要开销。 (假设即使没有可证明的开销,只是因为我很好奇它是开销),我能想到的唯一解决方案是在这里使用std::any(但这需要对象是可复制构造的)并且要么使使用std::any 作为成员变量的回调统一签名,或者只是将std::any 传递给函数(存储为函数指针)并放弃对回调状态的封装。但有件事告诉我有更好的解决方案......
【问题讨论】:
-
我不明白,如果
callback指向的东西总是 是Something,为什么还要使用void*?为什么不直接使用Something*? -
@Brian 提供
add_callback()的库不知道,例如libevent 中的event_new() -
或标准库中的示例,
qsort和bsearch。 -
TBH,在几乎任何涉及异步回调的情况下,虚拟调度的成本与其他一切的成本相比都可以忽略不计。
-
@Curious:这是一个从将自己定义为一个角落开始的问题。没有值类型,因为这需要复制。没有间接调度,因为那“需要”虚函数。等等。也不清楚您想要修复 C 方法的哪些缺陷:无法提供任意可调用对象(函子等),检查
void*参数是否实际上是它被强制转换为的类型,或别的什么。
标签: c++ c++11 callback c++17 type-erasure