实现具有多态检索的类型映射
Implementing a type map with polymorphic retrieval
我正在研究一个事件系统,该系统允许触发器向与给定类型相关的单个处理程序或所有处理程序发送事件。前者是基本的地图功能,而后者则符合要求……除非你想要多态行为。
class Parent {};
class Child : public Parent {};
// ...
Parent p; Child c;
Trigger trigger;
Handler h1(&p), h2(&c);
trigger.sendToType<Child>(Event()); // sends the event to h2; OK
trigger.sendToType<Parent>(Event()); // sends the event to h1 only; NO
处理程序是根据创建它们的指针类型注册的。h1
的"类型"为Parent
, h2
的"类型"为Child
。使用调度程序中使用的基本类型id映射(只是一些与类型相关的整数映射到Handler*
的向量),在向父级发送事件时无法向子级发送事件。
我能想到的唯一解决方案有几个缺点:
- O(n)查找发送到某个类型。
- 必须在代码库中添加反射
- 大量手动设置
理想情况下,我想要一个解决方案,其中开销减少到每次发送到类型查找(子类型的数量+ 1的实际类型),但这可能是不可能的。任何建议吗?
最简单的解决方案是使用dynamic_cast。就性能而言,它可能不是最佳的,但应该比map/hash
快。这是实现-在线测试
#include <iostream>
#include <string>
#include <vector>
struct Event
{
std::string what;
};
class Parent
{
public:
virtual void process(const Event& e)
{
std::cout << e.what << "Parent" << std::endl;
}
};
class Child : public Parent
{
public:
virtual void process(const Event& e) override
{
std::cout << e.what << "Child" << std::endl;
}
};
template<typename T>
void handler(Parent* obj, const Event& e)
{
if (T* tmp = dynamic_cast<T*>(obj))
tmp->process(e);
}
template<typename T, typename PARENT>
std::vector<T*> select_objects(const std::vector<PARENT*>& objects)
{
std::vector<T*> res;
for (auto obj : objects)
{
if (T* tmp = dynamic_cast<T*>(obj))
res.push_back(tmp);
}
return res;
}
int main()
{
std::vector<Parent*> objects = {new Parent, new Child};
Event e{"Hello from "};
std::cout << "All objects" << std::endl;
for (auto p : objects)
handler<Parent>(p, e);
std::cout << "Child objects only" << std::endl;
for (auto p : objects)
handler<Child>(p, e);
// here we can build an index to access objects faster
std::cout << "Child objects only using select" << std::endl;
std::vector<Child*> children = select_objects<Child>(objects);
for (auto o : children)
o->process(e);
}
输出:All objects
Hello from Parent
Hello from Child
Child objects only
Hello from Child
Child objects only using select
Hello from Child
UPDATE:你可以建立一些索引来更快地访问对象
相关文章:
- 将类型映射到整数值后,如何在给定整数值的情况下恢复类型?
- C++17:在编译时将类型映射到整数值
- 为C++重载函数创建SWIG类型映射
- 返回各种类型的函数的SWIG类型映射
- 类型映射资源并将列表转换为矢量(并返回)
- 有没有办法在 C++17 中创建编译时类型映射以进行类型检查?
- 如何在OpenCV中使用双类型映射进行重新映射
- SWIG 多参数类型映射适用于函数,但如果有多个构造函数,则不适用于构造函数
- Swig:如何类型映射c ++字符串常量和python字符串?
- SWIG 类型映射的 python 列表到双倍 *
- SWIG -- 在扩展中使用类型映射
- 嵌入的多个变体类型映射
- SWIG类型映射中的内存释放
- 您将如何为 std::list<std::string> 创建一个类型映射,以在<String> List in C++ 中为 Java 在 SWIG 中创建?
- SWIG-为具有四个参数的函数创建一个类型映射,该参数传递一个字节数组
- 在C++中将类类型映射到其他类类型
- C func 到C++具有非双射参数类型映射的实例成员蹦床
- Swig 界面中的类型映射错误
- 如何在 swig 中引用类型映射类
- 将实例变量类型映射到模板成员函数