2016-11-08 2 views
0

Entity Component System의 Entity Manager가 수정되었습니다. 구성 요소에는 기능이 중복되어 있지 않기 때문에 내가 저장할 수있는 공유 기반을 갖기를 원하지 않습니다. 인스턴스화 된 템플릿 형식을 추적하십시오. C++

그래서 나는 이런 식으로 뭔가를 내놓았다 :

#include <vector> 
#include <memory> 
#include <iostream> 

class Component1{}; 
class Component2{}; 
class Component3{}; 

class Manager{ 
public: 
    template<typename T> static std::vector<std::shared_ptr<T>> component; 

    template<typename T> static std::shared_ptr<T> getComponent(int nth){ 
    return component<T>[nth]; 
    } 

    template<typename T> static std::shared_ptr<T> addComponent(int nth){ 
    return component<T>[nth] = shared_ptr<T>(new T()); 
    } 

    static void addEntity(){ 
    // push back a nullptr for every instantiated component<> 
    } 

    static void removeEntity(int nth){ 
    // set the nth index of every component<> to nullptr 
    } 
}; 

template<typename T> 
std::vector<std::shared_ptr<T>> Manager::component = std::vector<std::shared_ptr<T>>(); 

int main(){ 
    Manager::component<Component1>; 
    Manager::component<Component2>; 
    Manager::component<Component3>; 

    Manager::addEntity(); 
    auto cmp2 = Manager::getComponent<Component2>(0); 

    Manager::removeEntity(0); 

    std::cin.get(); 
    return 0; 
} 

나는 두 가지 기능에 대한 인스턴스화 된 구성 요소를 반복 할 수 있습니까? Type_info의 벡터를 사용하여 Component 유형을 저장하려고 시도했지만 템플릿 인자로 사용할 적절한 유형을 얻을 수 없었습니다.

답변

2

템플릿 메타 프로그래밍 트릭을 사용하여 get a unique ID for your types으로 시작할 수 있습니다. 그런 다음 변수 템플릿 벡터 대신 고유 유형 ID가 인 맵을 사용할 수 있습니다. 기본 컴포넌트 클래스와 함께 다형성을 도입하고 런타임 비용을 줄이기 위해 static_cast를 추가하면 이전 addComponentgetComponent 메소드를 쉽게 다시 구현할 수 있습니다. 지도 액세스로 인해 약간 더 많은 비용이 드는 것이지만 결국에는 addEntityremoveEntity을지도를 반복하면서 구현할 수 있습니다.

다음은 상기 아이디어를 내 구현 : 당신은 이미 (C++ 14을 사용하고 있기 때문에

#include <vector> 
#include <map> 
#include <memory> 
#include <iostream> 

typedef void(*unique_id_type)(); 

template <typename... Arguments> 
struct IdGen { 
    static constexpr inline unique_id_type get_unique_id() 
    { 
     return &IdGen::dummy; 
    } 

private: 
    static void dummy() {}; 

}; 

class Component {}; 
class Component1 : public Component {}; 
class Component2 : public Component {}; 
class Component3 : public Component {}; 

class Manager { 
public: 
    static std::map<unique_id_type, std::vector<std::shared_ptr<Component>>> components; 

    template<typename T> static std::shared_ptr<T> getComponent(int nth) { 
     return std::static_pointer_cast<T>(components[IdGen<T>::get_unique_id()][nth]); 
    } 

    template<typename T> static std::shared_ptr<T> addComponent(int nth) { 
     return std::static_pointer_cast<T>(components[IdGen<T>::get_unique_id()][nth] = std::shared_ptr<T>(new T())); 
    } 

    static void addEntity() { 
     for (auto& component : components) 
      component.second.push_back(nullptr); 
    } 

    static void removeEntity(int nth) { 
     for (auto& component : components) 
      component.second[nth] = nullptr; 
    } 
}; 

std::map<unique_id_type, std::vector<std::shared_ptr<Component>>> Manager::components = { 
    { IdGen<Component1>::get_unique_id(), {} }, 
    { IdGen<Component2>::get_unique_id(), {} }, 
    { IdGen<Component3>::get_unique_id(), {} }, 
}; 

int main() { 
    Manager::addEntity(); 
    auto cmp2 = Manager::getComponent<Component2>(0); 

    Manager::removeEntity(0); 

    std::cin.get(); 
    return 0; 
} 

PS =이 코드는 constexpr 및 목록 초기화 등 C++ 11 기능을 사용하지만, 심지어하지만 C++로 질문하지 않았다. 14), 나는 그것이 문제가 아니라고 생각한다.

PS 2 = static_cast로 다운 캐스팅 했으므로 구성 요소에 가상 상속을 사용하면 안됩니다 (why).

관련 문제