【问题标题】:What Type Collection Can I Access By Class Type and Return Not Found When Necessary我可以按类类型访问什么类型的集合,必要时找不到返回
【发布时间】:2018-03-05 04:14:24
【问题描述】:

对于冗长的、可能令人困惑的标题,我会尽力澄清。所以情况就是这样,我有一个组件向量(自定义类)的元组。每个组件都有一个 id,它对应于它在元组中的相应向量中的索引。组件属于一个实体,所以我希望实体跟踪它拥有的组件的所有 id。当然,如果不知道它所属的组件类型,ID 将毫无意义,这样我就可以将它从元组中拉出来。所以我希望实体有一个集合,也许是一个std::unordered_map,通过它我可以提供一个类类型并获取适当的索引,或者一些数字(在本例中为SHRT_MAX)告诉我实体没有这样的组件。

这似乎可以使用枚举和 switch 语句,但似乎也没有必要遍历 switch 语句的每个分支来为元组的 get 函数提供正确的类,所以我想知道是否有更好的方法。

我提供了我的代码示例,其中包含我正在寻找的注释示例:

#include <tuple>
#include <vector>
#include <unordered_map>

class Component {
    unsigned short id;
};

class CameraComponent : public Component {

};

class VehicleComponent : public Component {

};

class Entity {
    //This is kind of the data structure I am thinking about so far
    //std::unordered_map<ComponentType, unsigned short> components
};

class EntityManager {
private:
    //This is the tuple I am talking about
    static std::tuple<std::vector<CameraComponent>, std::vector<VehicleComponent>> components;
public:
    //This is used to make accessing the tuple more convenient
    template<class T>
    static auto& Components();

    //This is kind of function I would like to be able to use
    template<class T>
    static T& GetComponentFromEntity(Entity& e);
};

//Initialize the static tuple
std::tuple<std::vector<CameraComponent>, std::vector<VehicleComponent>> EntityManager::components;

//This is used to make accessing the tuple more convenient
template<class T>
auto& EntityManager::Components()
{
    return std::get<std::vector<T>>(components);
}

//This is kind of function I would like to be able to use
template<class T>
T& EntityManager::GetComponentFromEntity(Entity& e) {
    //unorded_map<ComponentType, unsigned short>::iterator itr;
    //itr = e.components.find(T);
    //if(itr = e.components.end())
        //return SHRT_MAX;
    //return Components<T>()[itr];
}

int main() {
    return 0;
}

任何帮助将不胜感激(我还想强调,我并没有结婚使用 unordered_map,这只是我想到的第一件事)。提前致谢。

【问题讨论】:

  • 您可能正在寻找std::type_index。它的发明几乎就是为了这个确切的目的 - 作为容器中的查找键,用于按类型查找。
  • @IgorTandetnik 这不仅仅是我可能正在寻找的,这正是我正在寻找的。事实上,我什至可以使用typeid(std::vector&lt;VehicleComponent&gt;),这出于不同的原因非常棒。非常感谢,我会把正确的代码贴出来,供以后求知的人参考
  • @IgorTandetnik 很抱歉这样选择你的大脑,但是当我使用常量时效果很好,但当我尝试 e.components.insert(std::make_pair&lt;std::type_index, unsigned short&gt;(typeid(VehicleComponent), i)) 时,其中 iunsigned short 参数变量。我收到cannot convert argument 2 from 'unsigned short' to 'unsigned short&amp;&amp;' 错误。根据对堆栈溢出的一些响应,我将插入更改为e.components.insert(std::make_pair(typeid(VehicleComponent), i)),但没有模板,但现在我收到cannot convert from 'initializer list' to '_Mypair' 错误。有什么想法吗?
  • 试试std::make_pair&lt;const std::type_index, unsigned short&gt;(注意const)。这就是std::unordered_map&lt;std::type_index, unsigned short&gt; 的正确value_type。或者,如果您不需要insert 的返回值,这更简单:e.components[typeid(VehicleComponent)] = i;

标签: c++ templates tuples entity c++14


【解决方案1】:

正如 Igor Tandetkik 所建议的,答案是使用unordered_mapstd::type_index,方法类似于以下:

#include <tuple>
#include <vector>
#include <unordered_map>
#include <typeindex>
#include<iostream>
using std::cout;
using std::getchar;

class Component {
public:
    unsigned short id = SHRT_MAX;
};

class CameraComponent : public Component {
};

class VehicleComponent : public Component {
};

class Entity {
public:
    std::unordered_map<std::type_index, unsigned short> components;
};

class EntityManager {
private:
    //This is the tuple I am talking about
    static std::tuple<std::vector<CameraComponent>, std::vector<VehicleComponent>> components;
public:
    //This is used to make accessing the tuple more convenient
    template<class T>
    static auto& Components();

    //This is what I want
    template<class T>
    static T* GetComponentFromEntity(Entity& e);
};
//Initialize the static tuple
std::tuple<std::vector<CameraComponent>, std::vector<VehicleComponent>> EntityManager::components;

//This is used to make accessing the tuple more convenient
template<class T>
auto& EntityManager::Components()
{
    return std::get<std::vector<T>>(components);
}

template<class T>
T* EntityManager::GetComponentFromEntity(Entity& e) {
    std::unordered_map<std::type_index, unsigned short>::iterator itr;
    itr = e.components.find(typeid(T));
    if(itr == e.components.end())
        return nullptr;
    return &Components<T>()[itr->second];
}

int main() {
    Entity e;
    VehicleComponent v;
    v.id = EntityManager::Components<VehicleComponent>().size();
    EntityManager::Components<VehicleComponent>().push_back(v);
    e.components.insert(std::make_pair<std::type_index, unsigned short>(typeid(VehicleComponent), 0));
    cout << EntityManager::GetComponentFromEntity<VehicleComponent>(e)->id;
    getchar();
    return 0;
}

再次感谢 Igor Tandetnik!

【讨论】:

    猜你喜欢
    • 2013-08-25
    • 1970-01-01
    • 2011-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多