【问题标题】:Get the most derived type from std::type_index for component从组件的 std::type_index 获取最多派生类型
【发布时间】: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。所以,如果你传递一个派生较少的类,那就是你的Ttypeid(T) 不等于typeid(*component)
  • 我试过typeid(component) 但不是*component,现在试试

标签: c++ templates metaprogramming typeid


【解决方案1】:

您需要执行typeid(*component) 来获取指向对象的动态类型,而不是其类型名或指向它的指针的声明类型。

当然,typeid(T) 将永远是T。所以,如果你传递一个派生较少的指针T* component,那么typeid(T) 不等于typeid(*component)

另外,如果您在尝试 typeid(component) 时没有取消引用,那么您应该得到指针的类型,而不是它指向的类型,这不应该是正确的。

最后,尽管在您的情况下这似乎已经得到保证,但值得注意的是,对象需要是多态的才能使其工作,即至少具有一个虚拟成员函数。否则,这个需要的 RTTI 将不存在。

【讨论】:

    猜你喜欢
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 2011-01-11
    相关资源
    最近更新 更多