如何从ECS中的模板方法获取组件?
How to get component from template method in ECS?
我正在开发实体组件系统游戏引擎,在从实体检索组件时遇到麻烦。
这是我对实体的实现:
class Entity {
public:
Entity(int l_id);
// ...
template <typename T>
std::shared_ptr<T> GetComponent() { // T = CRender, CInput, etc
for (auto& component : m_components) {
if (typeid(component.second.get()) == typeid(T*)) {
return std::dynamic_pointer_cast<T>(component.second);
}
}
return nullptr;
}
private:
int m_id;
std::string m_name;
std::unordered_map<ComponentType, std::shared_ptr<Component>> m_components;
组件类型是包含在组件类中的枚举类。实体指向的组件是静态类型的组件,但动态类型的 CRender、CInput 等。也就是说,我有一堆组件作为组件类的子级。 此外,我保留了不同类中每个组件的一些smart_pointers。 代码的思想是检查映射中的每个组件,并检查智能指针指向的指针的类型
那个 GetComponent(( 方法是我试图开始工作的。 这里的目标是能够通过执行以下操作来检索任何组件(渲染组件的 CRender 等(:
std::shared_ptr renderComponent = entity.GetComponent<CRender>();
很难弄清楚如何做到这一点,因为我将组件存储在地图中,因此每种类型只能有 1 个组件。
我做错了什么?我也欢迎您有更好的实现设计想法。提前感谢!
这似乎是这里的问题:
if (typeid(component.second.get()) == typeid(T*))
主要问题是,typeid
与指针一起使用时不会像您期望的那样获得派生类型。它将为您提供"指向组件的指针"typeid
,因此您将始终评估typeid(pointer-to-Component) == typeid(pointer-to-DerivedComponent)
。
至于改进,在您的代码中,您没有利用按std::map
的关键功能查找。您可以将 GetComponent 函数更改为非模板函数,而不是遍历映射,该函数将枚举值作为参数并使用该函数执行映射查找。
由于您最初编写的是模板函数,因此作为替代方法,将映射的键类型更改为std::type_index
可能会有所帮助。这将允许您执行以下操作:
std::map<std::type_index, std::shared_ptr<Component>> components;
template <typename T>
std::shared_ptr<T> GetComponent() {
return std::dynamic_pointer_cast<T>(components[typeid(T)]);
}
并且您应该包含逻辑来处理找不到组件的情况,就像在原始代码中所做的那样。
相关文章:
- 将成员函数指针作为参数传递给模板方法
- 模板方法访问正向声明的类仅在没有此指针的情况下无法编译
- C++11:模板方法的模板函数调用无法编译?
- 模板规范获取'Ambiguous call to overloaded function'
- 如何从ECS中的模板方法获取组件?
- 使用 SFINAE 设计模板方法
- 一个模板方法,用于同时接受常量和非常量参数
- C++模板方法中的循环依赖关系
- 在 C++ 中使用模板方法重写类方法
- 类中的模板方法
- 基于枚举参数调用专用模板方法
- 模板中的模板方法 - 实例声明和类方法声明签名不同
- 可变参数模板方法
- 使用模板方法为标头提供空 cpp 时出现问题
- SFINAE 方法在 clang 中完全禁用基类的模板方法
- 将函数和成员函数传递给模板方法
- 从非模板类调用专用模板方法
- 使用模板时获取"Trigger Breakpoint Error at delete"
- C++模板方法和获取结果的设计
- 从模板模板方法参数中获取类型