C++事件调度员 - 回调铸造问题

发布于 2025-01-23 06:52:54 字数 3654 浏览 5 评论 0 原文

我正在冒险使用Visual Studio 2022中使用C ++ 17创建EventDisPatcher。基本上,我存储了一个字符串(ID)来识别事件,并通过registerevent()方法在vector中识别vector中的回调(lambda,function或a类)。 。 然后,我需要调用将事件传递给参数的dispatchevent()方法。此事件将事件ID作为参数接收。在内部,dispatchevent()方法循环找到具有相应ID的事件,并执行先前存储的回调,将事件传递给回调。 当使用通用事件时,一切都可以完美。 (只需评论DocustomeVents()方法中的所有内容;

问题

在创建从通用事件派生的事件时,在此示例中,Customevent将无法执行铸件并发出以下错误:

错误c2440:< function-style-cast>':无法从'initializer list''转换为'eventprops':line 41

在此 - > m_eventprops.push.push_back( EventProps(ID,回调);

到目前为止,我所看到的都无法帮助我解决这个问题

我一直在研究铸造,但是 请

按照以下代码

#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;
}

I'm venturing into creating an EventDispatcher using C++ 17 in Visual Studio 2022. Basically I store a string (id) to identify the event and a callback (lambda, function or method of a class) in a vector through the RegisterEvent() method.
Then I need to call the DispatchEvent() method passing the event as a parameter. This event receives the event id as a parameter. Internally the DispatchEvent() method loops to find the event with the corresponding id and executes the previously stored callback passing the event to the callback.
When using the generic Event event, everything works perfectly. (Just comment out all the content inside the doCustomEvents() method;

PROBLEM

When creating an event derived from the generic event, in this example CustomEvent it fails to perform the casting and issues the following error:

Error C2440 : <function-style-cast>': cannot convert from 'initializer list' to 'EventProps' : LINE 41

HERE -> m_EventProps.push_back(EventProps(id, callback));

I've been studying a lot about casting, but nothing I've seen so far has been able to help me solve this problem.

Could someone please help me?

Thank you very much!

Follow the code below:

#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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

人海汹涌 2025-01-30 06:52:54

这个问题可能处于人们通常会关闭的问题的边缘,但是MSVC在这里提供了一个真正无用的错误消息,使您的生活更加艰难。 (您可能想尝试升级编译器; godbolt.org上的最新MSVC给出了更多有用的信息。)

问题与

dispatcher.RegisterEvent<CustomEvent>("custom_0", [](CustomEvent e) { DEBUG("[Lambda] " + e.ToString()); });

以下几行有关。

dispatcher.registerevent&lt; customevent&gt; 采取第二个类型的参数 std :: function&lt; void(customevent)&gt; ,然后继续使用它来尝试构建 EventProps 。但是,EventProps想要的构造函数是 std :: function&lt; void(event)&gt; 。编译器无法将仅接受 CustomeVent s的函数转换为接受 all all 事件 s的函数。

您需要模板 eventprops 本身,或调整 registerevent ,以将类型 t 的函数转换为一个功能,以获取所有 event s。

This question is probably on the edge of what people would normally close, but MSVC is making your life harder by giving a really useless error message here. (You might want to try upgrading your compiler; recent MSVC on godbolt.org give much more helpful messages.)

The problem is with

dispatcher.RegisterEvent<CustomEvent>("custom_0", [](CustomEvent e) { DEBUG("[Lambda] " + e.ToString()); });

and the following lines.

dispatcher.RegisterEvent<CustomEvent> takes a second argument of type std::function<void(CustomEvent)> and then proceeds to use it to try to construct an EventProps. However what the constructor of EventProps wants is a std::function<void(Event)>. There is no way for the compiler to convert a function that only accepts CustomEvents into a function that accepts all Events.

You need to either template EventProps itself, or adapt RegisterEvent to convert a function taking events of type T into a function taking all Events.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文