【发布时间】:2020-01-10 15:19:01
【问题描述】:
我有以下代码允许我使用实体组件系统。但是,由于模板的性质,从std::vector<HE2_Component*> 添加组件会导致它们以HE2_Component 的类型ID 而不是它们最派生的形式添加(代码底部的示例)。如何强制它正确识别组件类型?
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,typeid(T)不等于typeid(*component)。 -
我试过
typeid(component)但不是*component,现在试试
标签: c++ templates metaprogramming typeid