2017-07-07 141 views
0

我有一個模板類ComponentCache,它本質上是一個圍繞std::vector的包裝,除了它只提供對數據的隨機訪問。C++推導模板參數的問題

template<class T> 
class ComponentCache 
{ 
public: 
    ComponentCache() 
    { 
    m_Components.reserve(1024); 
    } 

    ~ComponentCache() 
    { } 

    //Get a component stored at some index. 
    //If the index is greater than the size of the index, 
    //resize it to the size of the index + 128 
    T& GetComponent(const std::uint32_t& index) 
    { 
    if(index >= m_Components.size()) 
    { 
     std::uint32_t newSize = index + 128; 
     m_Components.resize(newSize); 
    } 

    return m_Components.at(index); 
    } 
private: 
    std::vector<T> m_Components; 
}; 

我還有另外一個模板類,ComponentStorage,那基本上是圍繞的std ::元組的包裝>。

template<class... T> 
class ComponentStorage 
{ 
public: 
    ComponentStorage() 
    { } 
    ~ComponentStorage() 
    { } 


    //Gets a component at some index from the tuple of components 
    template<class Component> 
    Component& GetComponent(const aecs::Entity& index) 
    { 
    return std::get<aecs::Component::ComponentCache<Component>> 
    (m_ComponentLines).GetComponent(index); 
    } 

private: 
    std::tuple<aecs::Component::ComponentCache<T>...> m_ComponentLines; 
}; 

最後,我還有一個模板類,World,充當保持內存池的地方和邏輯接近海誓山盟的ComponentStorage類。

template<class... Components> 
class World 
{ 
    struct EntityMetadata 
    { 
    std::bitset<sizeof...(Components)> ComponentBitset; 
    bool IsActive = false; 
    }; 
public: 
    World(std::size_t size = 128) 
    { 
    m_EntityMetadata.resize(size); 
    } 
    ~World() 
    { } 

    /*Entity Management*/ 
    const aecs::Entity& CreateEntity() 
    { 
    auto entity = m_EntityPool.Create(); 
    if(entity != 0xFFFFFFFF) 
    { 
     auto entityIndex = aecs::GetIndexFromEntity(entity); 
     m_EntityMetadata.at(entityIndex).IsActive = true; 
    } 
    return std::move(entity); 
    } 
    void DestroyEntity(const aecs::Entity& entity) 
    { 
    if(entity == 0xFFFFFFFF) 
    { 
     return; 
    } 
    auto entityIndex = aecs::GetIndexFromEntity(entity); 
    m_EntityMetadata.at(entityIndex).IsActive = false; 
    m_EntityPool.Destroy(entity); 
    } 
    const std::vector<aecs::Entity>& GetActiveEntities() 
    { 
    return m_EntityPool.GetActiveEntities(); 
    } 
    const bool IsEntityActive(const aecs::Entity& entity) 
    { 
    auto entityIndex = aecs::GetIndexFromEntity(entity); 
    return m_EntityMetadata.at(entityIndex).IsActive; 
    } 

    /*Component Management*/ 
    template<class Component> 
    Component& GetComponentFromEntity(const aecs::Entity &entity) 
    { 
    const std::uint32_t index = aecs::GetIndexFromEntity(entity); 
    return m_ComponentStorage.GetComponent<Component>(index); 
    } 
    template<class Component> 
    void AddComponentToEntity(const aecs::Entity& entity) 
    { 
    //TODO: Implement 

    auto entityIndex = aecs::GetIndexFromEntity(entity); 

    m_EntityMetadata.at(entityIndex).ComponentBitset.set(
     aecs::mpl::IndexOf<Component, std::tuple<Components...>>::value); 
    } 
    template<class Component> 
    void RemoveComponentFromEntity(const aecs::Entity& entity) 
    { 
    //TODO: Implement 
    auto componentIndex = aecs::mpl::IndexOf<Component, 
     std::tuple<Components...>>::value; 
    auto entityIndex = aecs::GetIndexFromEntity(entity); 

    m_EntityMetadata.at(entityIndex).ComponentBitset.reset(componentIndex); 

    } 
    template<class Component> 
    const bool EntityHasComponent(const aecs::Entity& entity) 
    { 
    auto componentIndex = aecs::mpl::IndexOf<Component, 
     std::tuple<Components...>>::value; 
    auto entityIndex = aecs::GetIndexFromEntity(entity); 

    std::bitset<sizeof...(Components)> tempBitset; 
    tempBitset.set(componentIndex); 


    return (m_EntityMetadata.at(entityIndex).ComponentBitset & tempBitset) == 
                  tempBitset; 
    } 

private: 
    aecs::EntityPool m_EntityPool; 
    aecs::ComponentStorage<Components...> m_ComponentStorage; 

    std::vector<EntityMetadata> m_EntityMetadata; 
}; 

投擲它一起,它應該工作是這樣的:

struct Position 
{ 
    float x; 
    float y; 
}; 

struct Velocity 
{ 
    float x; 
    float y; 
}; 

int main() { 

    aecs::World<Position, Velocity> w; 

    const auto e = w.CreateEntity(); 
    Velocity& v1 = w.GetComponentFromEntity<Velocity>(e); 
    return 0; 
} 

不過,我得到關於GetComponentFromEntity以下編譯錯誤:

error: expected primary-expression before '>' token 
    return m_ComponentStorage.GetComponent<Component>(index); 

如果我轉它,以便它應該自動推斷出Component的類型,我反而會得到以下錯誤:

E:\CLion\AECS\aecs/World/World.h: In instantiation of 'Component& aecs::World<Components>::GetComponentFromEntity(const Entity&) [with Component = Velocity; Components = {Position, Velocity}; aecs::Entity = unsigned int]': 
E:\CLion\AECS\main.cpp:26:54: required from here 
E:\CLion\AECS\aecs/World/World.h:69:49: error: no matching function for call to 'aecs::ComponentStorage<Position, Velocity>::GetComponent(const uint32_t&)' 
    return m_ComponentStorage.GetComponent(index); 
               ^
In file included from E:\CLion\AECS\aecs/World/World.h:9:0, 
       from E:\CLion\AECS\main.cpp:2: 
e:\clion\aecs\aecs\componentstorage\componentstorage.h:27:14: note: candidate: template<class Component> Component& aecs::ComponentStorage<T>::GetComponent(const Entity&) [with Component = Component; T = {Position, Velocity}] 
    Component& GetComponent(const aecs::Entity& index) 
      ^
e:\clion\aecs\aecs\componentstorage\componentstorage.h:27:14: note: template argument deduction/substitution failed: 
In file included from E:\CLion\AECS\main.cpp:2:0: 
E:\CLion\AECS\aecs/World/World.h:69:49: note: couldn't deduce template parameter 'Component' 
    return m_ComponentStorage.GetComponent(index); 

看起來編譯器在編譯時應該沒有問題,因爲Component就是返回的結果。 我覺得我犯了一些明顯的錯誤,但一切看起來都是正確的。我是否忘記了有關模板的重要內容?

+0

你需要每個方法模板調用之前[MCVE] –

+1

使用模板的關鍵字(獨立型)模板類中:'m_ComponentStorage.template GetComponent (index);'讓編譯器知道'<'並不意味着少於'template parameters list starts' –

+1

@WF它真的被小於的困惑?還是它在模板名稱解析的第一階段不知道它是否是類型? – xaxxon

回答

1

把自己到時,它的解析行的編譯器的鞋子:

return m_ComponentStorage.GetComponent<Component>(index); 

類型的m_ComponentStorage取決於Components...,解析代碼時,這是個未知數。你怎麼可能知道GetComponent應該是什麼?

它可能是一個模板成員函數,但它也可以是一個簡單的成員變量。爲了理智,編譯器被指示假定他們正在處理該場景中的成員變量。

你可以告訴編譯它在處理使用

return m_ComponentStorage.template GetComponent<Component>(index);