c++ - 在没有类型删除的情况下用 C++ 构建事件驱动系统的设计模式?

标签 c++ generics events

事件驱动系统用于减少具有各种类型的多对多对象交互的大型系统中的依赖性。因此,它们的目标是在任意对象之间传递任意信息。这通常通过注册事件 handlers 来完成用event_manager , 在 handler 中使用类型删除,即:

void handle_some_event(event *e) {/*Downcast e to an assumed appropriate type and work with it*/}

但是,假设我们想要实现这样一个没有类型删除的系统。似乎某些语言特性,尤其是泛型,应该使之成为可能。 handlerevent_manager注册可以模板化,即(松散地):

template<typename event_type>
void event_manager::register_handler(std::function<void(event_type)> handler) {
    // Implementation
}

奋斗的是,应该怎样//Implementation这个功能是?收到处理程序后,需要将其存储到与event_type相关的容器中.但是为了避免类型删除,必须有一个容器 per event_type .

一个可能的选择是在模板类中使用静态容器,即:

template<typename event_type>
class handler_container {
public:
    inline static std::vector<std::function<void(event_type)>> handlers;
};

event_manager可以在相应的 handler_container<event_type>::handlers 中存储和执行处理程序容器。但是,这有一个明显的缺点,即实际上只能有一个 event_manager。 ,鉴于容器是静态的,因此在所有 event_managers 之间共享.也许这对大多数应用程序来说已经足够了,但它仍然是一个丑陋的解决方案。

是否有任何设计模式可以更清晰地解决此问题?

最佳答案

不是设计模式,但理论上它看起来像是 std::variant 的潜在用例.您可以将事件类型定义为所有可能事件选项的 std::variant 的别名,并且您的处理程序将是 C++20 的 template lambdas。使用 constexpr if 检查他们想要的类型.最后,生成事件的代码使用适当的事件类型初始化 std::variant,并使用 std::visit 调用所有处理程序。 .

std::variant 的使用似乎是一个潜在的可伸缩性问题,但如果处理程序编写得当,它们在添加更多变体时不应中断。

我不知道有任何使用这种“技术”的主要项目,所以我不会立即在生产代码中使用它。此外,它需要 C++20 才能在没有(太多)样板的情况下编写它,因此它可能不适用于大多数用例。但它看起来可行并且不需要类型删除。

关于c++ - 在没有类型删除的情况下用 C++ 构建事件驱动系统的设计模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70415237/

相关文章:

swift - 快速获取泛型的参数化类型?

java - 抽象方法的返回值是否可以是泛型类型

javascript - iPadOS 14 Apple Pencil 快速点击不起作用。 - HTML JavaScript ontouchstart/onpointerdown

矩形上的 JavaFx KeyEvent 不起作用

c++ - shared_ptr 析构函数、复制和不完整类型

c++ - 将项目添加到 QGraphicsItemGroup 使其不可见

c++ - 设置 eclipse 链接器以编译和运行 GLFW 应用程序 - 如何?

java - 使用 SWIG 将 c++ 包装到 java UnsatisfiedLinkError : HeaderJNI. new_Test()J

java - 使用 JAXB 映射通用的嵌套 XML 数据结构

c# - 将不同的枚举组合成一个参数 C#