从组件的 std::type_index 获取最多的派生类型
Get the most derived type from std::type_index for component
我有以下代码可以使用实体组件系统。但是,由于模板的性质,从 std::vector<HE2_Component*>
添加组件会导致它们添加的类型 ID 为 HE2_Component
而不是它们最派生的形式(代码底部的示例)。我怎样才能强制它正确识别组件类型?
template<typename T,
typename = std::enable_if_t<std::is_base_of_v<HE2_Component, T>>>
void addComponent(T* component)
{
components.insert(std::make_pair(std::type_index(typeid(T)), component));
component->host = this;
}
template<typename CompType,
typename = std::enable_if_t<std::is_base_of_v<HE2_Component, CompType>>>
inline void removeComponent()
{
auto it = components.find(std::type_index(typeid(CompType)));
if (it == components.end())
return;
components.erase(it->first);
}
template<typename CompType,
typename = std::enable_if_t<std::is_base_of_v<HE2_Component, CompType>>>
inline CompType* getComponent()
{
auto it = components.find(std::type_index(typeid(CompType)));
if (it == components.end())
{
throw std::runtime_error("Object does not contain this component!");
return nullptr;
}
return dynamic_cast<CompType*>(it->second);
}
//EXAMPLE HERE
//Setup
HE2_ComponentOwner* obj = new HE2_ComponentOwner();
HE2_ComponentOwner* obj2 = new HE2_ComponentOwner();
class A : virtual public HE2_Component { double f = 0.0; };
class B : virtual public HE2_Component { float b = 0.0f; };
class C : public HE2_Component { int x = 0; };
//Add some components from a vector to obj
std::vector<HE2_Component*> comps = { new A(), new B(), new C() };
for (auto x : comps)
obj->addComponent(x);
//Add some manually to obj2
obj2->addComponent(new A());
obj2->addComponent(new B());
obj2->addComponent(new C());
//This doesn't work
A* a = obj->getComponent<A>();
B* a = obj->getComponent<B>();
C* c = obj->getComponent<C>();
//This does work
A* a = obj2->getComponent<A>();
B* b = obj2->getComponent<B>();
C* c = obj2->getComponent<C>();
您需要typeid(*component)
获取指向对象的动态类型,而不是其类型名或指向它的指针的声明类型。
当然,typeid(T)
将永远是 T
。因此,如果您传递一个派生较少的指针类型 T* component
,则 typeid(T)
不等同于 typeid(*component)
.
此外,如果您尝试 typeid(component)
,而不取消引用,那么您应该得到指针的类型,而不是它所指向的类型,这不应该是正确的。
最后,虽然这在您的情况下似乎已经确定,但值得注意的是对象需要是多态的才能使其工作,即至少有一个虚拟成员函数。否则,这个需要的RTTI是不存在的。
我有以下代码可以使用实体组件系统。但是,由于模板的性质,从 std::vector<HE2_Component*>
添加组件会导致它们添加的类型 ID 为 HE2_Component
而不是它们最派生的形式(代码底部的示例)。我怎样才能强制它正确识别组件类型?
template<typename T,
typename = std::enable_if_t<std::is_base_of_v<HE2_Component, T>>>
void addComponent(T* component)
{
components.insert(std::make_pair(std::type_index(typeid(T)), component));
component->host = this;
}
template<typename CompType,
typename = std::enable_if_t<std::is_base_of_v<HE2_Component, CompType>>>
inline void removeComponent()
{
auto it = components.find(std::type_index(typeid(CompType)));
if (it == components.end())
return;
components.erase(it->first);
}
template<typename CompType,
typename = std::enable_if_t<std::is_base_of_v<HE2_Component, CompType>>>
inline CompType* getComponent()
{
auto it = components.find(std::type_index(typeid(CompType)));
if (it == components.end())
{
throw std::runtime_error("Object does not contain this component!");
return nullptr;
}
return dynamic_cast<CompType*>(it->second);
}
//EXAMPLE HERE
//Setup
HE2_ComponentOwner* obj = new HE2_ComponentOwner();
HE2_ComponentOwner* obj2 = new HE2_ComponentOwner();
class A : virtual public HE2_Component { double f = 0.0; };
class B : virtual public HE2_Component { float b = 0.0f; };
class C : public HE2_Component { int x = 0; };
//Add some components from a vector to obj
std::vector<HE2_Component*> comps = { new A(), new B(), new C() };
for (auto x : comps)
obj->addComponent(x);
//Add some manually to obj2
obj2->addComponent(new A());
obj2->addComponent(new B());
obj2->addComponent(new C());
//This doesn't work
A* a = obj->getComponent<A>();
B* a = obj->getComponent<B>();
C* c = obj->getComponent<C>();
//This does work
A* a = obj2->getComponent<A>();
B* b = obj2->getComponent<B>();
C* c = obj2->getComponent<C>();
您需要typeid(*component)
获取指向对象的动态类型,而不是其类型名或指向它的指针的声明类型。
当然,typeid(T)
将永远是 T
。因此,如果您传递一个派生较少的指针类型 T* component
,则 typeid(T)
不等同于 typeid(*component)
.
此外,如果您尝试 typeid(component)
,而不取消引用,那么您应该得到指针的类型,而不是它所指向的类型,这不应该是正确的。
最后,虽然这在您的情况下似乎已经确定,但值得注意的是对象需要是多态的才能使其工作,即至少有一个虚拟成员函数。否则,这个需要的RTTI是不存在的。