从 std::function 的向量中删除一个元素

6

我正在尝试在C++中编写一个观察者模式,因此我有一个包含事件名 -> 回调函数向量的映射表

回调函数存储在一个向量中

std::function<void(void *)>

所以地图看起来像这样
std::unordered_map<std::string, std::vector<std::function<void(void *)>>>

我可以向向量添加监听器并接收和响应事件通知。 我的问题在于实现分离。
所以std :: function无法进行比较,因此擦除/删除是不行的,因此我想搜索向量并手动进行比较。
我发现this question成功使用std :: function :: target来获取对底层指针的访问权限,但我不能使用它,因为我正在使用std :: bind初始化回调函数:
std::function<void(void *)> fnCallback = std::bind(&wdog::onBark, this, std::placeholders::_1)

我只想比较底层成员函数指针,或者将成员函数关联的底层对象指针与之进行比较。有什么方法吗?

我想避免将成员函数指针包装在包含哈希的对象中,尽管看起来我可能不得不这样做...


2
你能否提供一个示例,说明你想如何向地图中添加/删除项目? - Holt
看起来你已经知道答案了... :-) - skypjack
1
你不能真正做到这一点,而不将指向所讨论对象的指针存储为键。我的实现使用weak_ptr,并在事件分派之前检查集合以删除expired()。Attach是(shared_from_this(), &class::member),detach是(shared_from_this())。 - Robinson
一个例子会太长(包含模板和多个文件),抱歉 Holt。 - stack user
1个回答

2
当我这样做时,我会向监听代码返回一个令牌。
我的通常模式是在广播器中有一个 weak_ptr<function<sig>>,而令牌是一个 shared_ptr<void>(指向存储的弱指针)。
在广播时,我会过滤掉已经失效的目标,然后进行广播。目标可以通过清除、销毁或丢弃其令牌来注销。如果他们想永远不注销,那么在它们的实例中使用一个令牌向量是合理的方法。
如果你从不广播,这可能会导致旧的无用资源无端地挂起,因此在公共框架中,我可能需要一些更好的保证。但它否则轻便易用且快速。

你能否请提供一个上述内容的示例代码? - TheWaterProgrammer
@segme https://dev59.com/z1sW5IYBdhLWcg3w-bH_#34400239 是一个之前在SO上的代码片段。我不知道它是不是我公开发布的最好的,但应该能给你提供一些想法。 - Yakk - Adam Nevraumont

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