对于可能会引起混淆的冗长标题,我深表歉意,我将尝试清除该标题。因此,在这种情况下,我有一个由组件(自定义类)组成的 vector 元组。每个组件都有一个ID,该ID与其元组中各个 vector 的索引相对应。组件属于一个实体,因此我希望该实体跟踪其拥有的组件的所有ID。当然,如果不知道其所属的Component的类型,那么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,这只是我想到的第一件事)。提前致谢。

最佳答案

正如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!

关于c++ - 我可以按类类型访问什么类型的集合,并在必要时找不到返回值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49103396/

10-09 05:37
查看更多