gpt4 book ai didi

c++ - 从 vector 映射中查找并删除 std::function 对象

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:07:17 26 4
gpt4 key购买 nike

我目前正在尝试为我的游戏引擎实现一个消息系统。它使用以下形式的函数回调:

typedef std::function<void(const Message &)> Callback;

它维护一个消息列表:

mutable std::vector<std::unique_ptr<Message>> messageList;

以及签名的回调字典:

mutable std::map<std::string, std::vector<Callback>> callbackDictionary;

用于调用“绑定(bind)”到特定消息类型的所有回调。调用回调函数时,将传递相应的消息。到目前为止一切顺利。

为了更好地理解,这里是订阅方法,它允许用户添加一个函数方法,该方法会为订阅类型的每条消息调用。

void Messenger::Subscribe(Message::Type type, Callback callbackFunction) 
const
{
callbackDictionary[type].push_back(callbackFunction);
}

这里是它如何使用的示例(通过可点击的组件类)

messageBus.Subscribe("Message/Click", [this](const Message & message) {this->OnClick(static_cast<const ClickMessage &>(message)); });

现在我的问题:

我想实现一个取消订阅方法,该方法在字典的 vector 中找到一个函数/方法并将其删除。请注意,该函数可以订阅多种消息类型。我在想这样的事情:

void Messenger::UnSubscribe(Callback callbackFunction)
{
for (auto & pair : callbackDictionary)
{
auto & functionList = pair.second;
for (auto function : functionList)
{
if (function == callbackFunction)
functionList.erase(std::remove(functionList.begin(), functionList.end(), function), functionList.end());
// I am aware of issues that may appear from looping deleting while looping
}
}
}

但是,比较运算符 (==) 对于函数对象似乎未定义。我想不出一个简单的方法来解决这个问题。所以任何想法都非常受欢迎。我只是想根据经验避免某种 id 系统原因,这可能是一项繁琐的管理工作。尤其是在整个程序中随处可以添加各种函数和成员的情况下。

最佳答案

std::function 中没有相等运算符。可以在旧的 tr1::function 中找到基本原理N1667 :

operator== is unimplementable for tr1::function within the C++ language, because we do not have a reliable way to detect if a given type T is Equality Comparable without user assistance

另请注意,您正在传递 std::function<void(const Message &)>按值(value)。这意味着您也不能只比较它们的地址(这并不是一个好的解决方案,因为 std::function 很容易复制)。

解决方案一:

使用一些用户提供的key 和std::function 作为value并将它们存储在 map 中而不是 vector .

std::map<std::string, std::map<std::string, Callback>> callbackDictionary;
. . .
void Messenger::Subscribe(Message::Type type, const std::string& cbID, Callback cb);

void Messenger::UnSubscribe(const std::string& cbID);

解决方案 2:

使用 weak_ptr跟踪回调。

std::map<std::string, std::vector<std::weak_ptr<Callback>> callbackDictionary;
. . .
void Messenger::Subscribe(Message::Type type, std::shared_ptr<Callback> cb);

没有UnSubscribe根本不需要!您可以尽快自动取消订阅回调 weak_ptrnullptr .一个先决条件是监听器必须通过 shared_ptr 保持回调事件。 .

关于c++ - 从 vector 映射中查找并删除 std::function 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47249465/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com