gpt4 book ai didi

c++ - C++ 中的 Lambda 通用性

转载 作者:行者123 更新时间:2023-11-27 23:37:25 25 4
gpt4 key购买 nike

在用 C++ 实现一个简单的玩具事件循环时,我遇到了一个问题。我有一个接口(interface)(抽象类)Event它由不同类型的事件(键盘、异步调用……)实现。在我的示例中 SomeEvent是Event的实现。

enum class EventType {
SOME_EVENT = 0,
};

class Event {
public:
virtual ~Event() {}
virtual EventType get_event_type() = 0;
};

class SomeEvent: public Event {
public:
SomeEvent(): m_event_type(EventType::SOME_EVENT) {}
void bar() { std::cout << "hello" << std::endl; }
EventType get_event_type() { return this->m_event_type; }

public:
EventType m_event_type;
};

EventHandler是一个接受 Event 的 lambda ,用它做一些事情并且什么都不返回。我有 EventHandler 的 map 关联到事件类型。 ( map 指向此 MWE 中的 EventHandler,但在我最初的实现中,它当然指向一个 vector )

typedef std::function<void(std::unique_ptr<Event>)> EventHandler;

std::map<EventType, EventHandler> event_handlers;

template <class T>
void add_event_handler(
EventType event_type,
const std::function<void(std::unique_ptr<T>)> &event_handler) {
event_handlers[event_type] = event_handler; // Does not compile
}

当我使用 inject_event 注入(inject)事件时,我只是在 map 中获取事件处理程序并使用事件作为参数调用它。

void inject_event(std::unique_ptr<Event> event) {
event_handlers[event->get_event_type()](std::move(event));
}

问题来自这张 map 的通用性。它应该持有一个接受 Event 的处理程序但我想在采用接口(interface)的 lambda 和采用该接口(interface)的实现的 lambda 之间没有继承链接,所以 it fails因为它不能分配 std::function<void(SomeEvent)>到 ``std::function` 类型的变量。

我一直在摸不着头脑,我的 C++ 生锈了,根本不是最新的。你会怎么做?语言中是否存在允许我以通用方式指定 lambda 的模式或功能?尝试使用 autoEventHandler定义,但似乎不允许。

最佳答案

好吧,C++ 的趋势是更喜欢静态多态性而不是动态多态性(实际上,静态或编译时一切都真的......);在你的情况下 - 你不能在运行时发生意外事件类型

因此,也许您可​​以忘记示例中的大部分代码,并尝试基于 std::variant 的代码。 :

  • 根据事件类型将您的事件处理代码模板化。
  • 代替EventType - 只需使用 std::variant::index()在事件上获取可能的事件类型中的数字类型索引;或者更好 - 根本不要使用它,您的事件类型模板可能就足够了。
  • 代替class Eventclass SomeEvent : Event ,你会得到 using Event = std::variant<events::Keyboard, events::Foo, events::Some> .也许你会有
    namespace events { 
    class Base { void bar() { /* ... */ } };
    class Foo : class Base { /* ... */ };
    }
    所有事件都继承自 Base (但不是虚拟的)。
  • 一个Event不需要显式存储或读取它的类型 - 它总是知道(除非你主动删除类型)。
  • 不再需要通过 Event*的,你可以通过 Event s 按值或按移动引用。所以不再std::unique_ptr类不匹配。
  • 至于你的 lambda,它很可能变成:

    void inject_event(Event&& event) {
    std::visit(event_handlers,event);
    }

    event_handler作为visitor .

现在 - 的确,您不能总是逃避动态多态性;有时你可以,但你工作的组织/公司太迟钝/笨拙,不允许这种情况发生。但是,如果您能做到这一点,可能会省去很多麻烦。

关于c++ - C++ 中的 Lambda 通用性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58248222/

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