提问人:Donavan Carvalho 提问时间:4/23/2022 最后编辑:Donavan Carvalho 更新时间:4/25/2022 访问量:379
C++ 事件调度程序 - 回调转换问题
C++ Event Dispatcher - callback casting problem
问:
我正在冒险在 Visual Studio 2022 中使用 C++ 17 创建事件调度程序。基本上,我通过 RegisterEvent() 方法在向量中存储一个字符串 (id) 来标识事件和一个回调(lambda、函数或类的方法)。 然后,我需要调用 DispatchEvent() 方法将事件作为参数传递。此事件接收事件 ID 作为参数。在内部,DispatchEvent() 方法循环查找具有相应 id 的事件,并执行先前存储的回调,将事件传递给回调。 使用通用 Event 事件时,一切正常。(只需注释掉 doCustomEvents() 方法中的所有内容;
问题
创建从泛型事件派生的事件时,在此示例中,CustomEvent 无法执行强制转换并发出以下错误:
Error C2440 : <function-style-cast>': cannot convert from 'initializer list' to 'EventProps' : LINE 41
这里 -> m_EventProps.push_back(EventProps(id, callback));
我一直在研究很多关于铸造的知识,但到目前为止,我所看到的任何东西都无法帮助我解决这个问题。
有人可以帮我吗?
谢谢!
请遵循以下代码:
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#define DEBUG(x) std::cout << x << std::endl;
#define BIND(fn) [this](auto...args) -> decltype(auto) { return this->fn(args...); }
class Event
{
public:
std::string Id;
Event(std::string id) : Id(id) { }
std::string ToString() { return "Event(id=" + Id +")"; }
};
class CustomEvent : public Event
{
public:
std::string Message;
CustomEvent(std::string id, std::string message) : Event(id), Message(message) { }
std::string ToString() { return "CustomEvent(id=" + Id + ", message=" + Message + ")"; }
};
struct EventProps
{
public:
std::string Id;
std::function<void(Event)> Callback;
EventProps(std::string id, std::function<void(Event)> callback) : Id(id), Callback(callback) { }
};
class EventDispatcher
{
private:
std::vector<EventProps> m_EventProps;
public:
template<typename T>
void RegisterEvent(std::string id, std::function<void(T)> callback)
{
m_EventProps.push_back(EventProps(id, callback));
}
void DispatchEvent(Event event)
{
for (int i = 0; i < m_EventProps.size(); i++)
{
EventProps props = m_EventProps[i];
if(props.Id == event.Id) props.Callback(event);
}
}
};
void globalCallback(Event e) { DEBUG("[Global] " + e.ToString()); }
void customGlobalCallback(CustomEvent ce) { DEBUG("[Global] " + ce.ToString()); }
class Application
{
public:
EventDispatcher dispatcher;
Application()
{
doEvents();
doCustomEvents(); // Nothing works here
}
void doEvents()
{
dispatcher.RegisterEvent<Event>("event_0", [](Event e) { DEBUG("[Lambda] " + e.ToString()); });
dispatcher.RegisterEvent<Event>("event_1", globalCallback);
dispatcher.RegisterEvent<Event>("event_2", BIND(Application::OnEvent));
dispatcher.DispatchEvent(Event("event_0"));
dispatcher.DispatchEvent(Event("event_1"));
dispatcher.DispatchEvent(Event("event_2"));
}
void doCustomEvents()
{
dispatcher.RegisterEvent<CustomEvent>("custom_0", [](CustomEvent e) { DEBUG("[Lambda] " + e.ToString()); });
dispatcher.RegisterEvent<CustomEvent>("custom_1", customGlobalCallback);
dispatcher.RegisterEvent<CustomEvent>("custom_2", BIND(Application::OnCustomEvent));
dispatcher.DispatchEvent(CustomEvent("custom_0", "Hi custom 0"));
dispatcher.DispatchEvent(CustomEvent("custom_1", "Hi custom 1"));
dispatcher.DispatchEvent(CustomEvent("custom_2", "Hi custom 2"));
}
void OnEvent(Event e) { DEBUG("[Application::OnEvent] " + e.ToString()); }
void OnCustomEvent(CustomEvent ce) { DEBUG("[Application::CustomEvent] " + ce.ToString()); }
};
int main()
{
Application app;
}
答:
这个问题可能处于人们通常会关闭的边缘,但 MSVC 通过在此处提供真正无用的错误消息,使您的生活更加艰难。(您可能想尝试升级编译器;godbolt.org 上最近的 MSVC 提供了更多有用的消息。
问题出在
dispatcher.RegisterEvent<CustomEvent>("custom_0", [](CustomEvent e) { DEBUG("[Lambda] " + e.ToString()); });
和以下几行。
dispatcher.RegisterEvent<CustomEvent>
采用类型的第二个参数,然后继续使用它来尝试构造一个 .但是,EventProps 的构造函数想要的是一个 .编译器无法将仅接受 s 的函数转换为接受所有 s 的函数。std::function<void(CustomEvent)>
EventProps
std::function<void(Event)>
CustomEvent
Event
您需要自己进行模板化,或者进行调整以将采用类型事件的函数转换为采用所有 s 的函数。EventProps
RegisterEvent
T
Event
评论
EventProps
CustomEvent
Event