[英]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.