簡體   English   中英

C ++在模板中使用靜態const類成員

[英]C++ using a static const class member in a template

所以我有為c ++ 0X編寫的這段c ++代碼。 它曾經在MSVC 2012中進行編譯,但是現在我切換到MingW64 4.8.1,因為我對MSVC中缺少C ++ 11支持感到不滿意。 以下是實現簡單實體/組件系統的某些代碼的一部分。

這是我得到的錯誤:

if(e-> components.find(T :: ID)== e-> components.end())

未定義對EL :: Position3DComponent :: ID的引用ELEntityManager.h / Elementium / Elementium第64行C / C ++問題

這與使用T :: ID ...有關

這是我以前在MSVC 2012中使用此代碼的內容的一些進一步說明:

在每個組件中,我都有一個靜態const ELComponentID成員,該成員已初始化為組件的ID。 之所以使用它,是因為我需要輕松獲取具有特定組件的實體,因此我在ELEntityManager中使用了一個多圖,其鍵為ELComponentID,其值是unique_ptr,其中包含具有此類組件的ELEntity。

在ELEntity類中,我使用一個unordered_map,其鍵為ELComponentID,其值為包含所討論的ELComponent的unique_ptr。

是的,它確實占用了更多的內存,但是我這樣做主要是為了提高訪問速度。

文件ELEntityManager.h:

//Includes
#include <map>
#include <memory>
#include "ELEntity.h"
#include "ELComponent.h"

namespace EL{

class ELEntityManager
{
public:

//...

template<typename T> void addComponent(std::unique_ptr<ELEntity> e, std::unique_ptr<ELComponent> c)
{
    if(c == nullptr || e == nullptr)
        return;
    if(e->components.find(T::ID) == e->components.end())  //***** <-- This is where I get the error.
    {
        //...
    }
    //...
}

//...

private:
//******************************************
// Private data members
//******************************************
    std::multimap<ELComponentID, std::unique_ptr<ELEntity> > entities;
};    

};// End namespace

文件ELEntity.h:

//Includes
#include <unordered_map>
#include <memory>
#include "ELComponent.h"

namespace EL{

class ELEntity
{
    friend class ELEntityManager;

//...

private:
//******************************************
// Private data members
//******************************************
    /**The map of ComponentIDs with their components.*/
    std::unordered_map<ELComponentID, std::unique_ptr<ELComponent> > components;
};

};// End namespace

文件ELComponent.h:

//Includes
#include <unordered_map>
#include <functional>
#include <string>
#include <vector>
#include "ELMath.h"


namespace EL{

/**
* Component IDs.
*/
enum ELComponentID {
    LogicalDevice = 1,  // Start the enum at 1.
    Viewport,
    Position3D,
    Position2D,
    Orientation,
    PhysicsRK4
};

/**
* Base component class.
*/
struct ELComponent
{
};

/**
* Position3D component, derives from ELVector3D in EL::Math.
*/
struct Position3DComponent: public ELComponent, EL::Math::ELVector3D
{
    static const ELComponentID ID = Position3D;
};

//...

然后在main.cpp中將其作為測試(包括所有必需的include等):

EL::ELEntityManager em;

std::unique_ptr<EL::ELEntity> e(new EL::ELEntity());
std::unique_ptr<EL::Position3DComponent> obj(new EL::Position3DComponent());

obj->x = 1.0;
obj->y = 2.0;
obj->z = 3.0;

em.addComponent<EL::Position3DComponent>(std::move(e), std::move(obj));

現在我的問題是,我是否在做某些特定於gcc的錯誤,g:cc / mingw不支持T :: ID,或者在最終的c ++ 11實現中發生了什么變化,而MSVC 2012並未實現?

如何解決此錯誤? 如果在c ++ 11中無法再執行此操作,或者gcc中存在錯誤,我可以通過其他方式執行此操作嗎?

提前非常感謝您的答復! :)

我認為海灣合作委員會是正確的。 從您發布的代碼來看,在我看來您沒有為靜態數據成員提供定義

由於將輸入中的T::ID傳遞給std::unordered_map::find() ,該參數以引用的形式接受參數,因此 ,您使用的是odr使用ID (ODR代表一個定義規則,簡而言之,odr使用意味着,表示編譯器需要知道該對象的地址)。

由於需要靜態數據成員的地址,但是沒有提供全局名稱空間的定義,因此最終會導致鏈接器出現無法解析的符號錯誤。

根據C ++ 11標准的9.4.2 / 3段:

如果非易失性const靜態數據成員是整數或枚舉類型,則其在類定義中的聲明可以指定大括號或相等初始化器 ,其中每個作為賦值表達式的 初始化子句都是一個常量表達式(5.19 )。 [...] 如果在程序中使用了成員(3.2),則成員仍應在名稱空間范圍中定義,並且名稱空間范圍定義不應包含初始化程序

因此,要解決該問題,只需在.cpp文件(或僅一個.cpp文件包含的標頭)的名稱空間范圍內添加定義:

const ELComponentID Position3DComponent::ID;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM