2012-01-08 61 views
3

我一直在對這個問題進行一些研究,但還沒有能夠提出解決方案。基本上我需要在模板類中初始化一個靜態常量類型變量。模板類中的靜態常量類型

class MyType 
{ 
public: 
    MyType (int a, int b) { } 
}; 

template <class T> 
class MyClass 
{ 
public: 
    static const MyType Type; 
}; 

在cpp中初始化類型將產生鏈接器錯誤。在頭文件中初始化Type會使它多次初始化。由於它是一個非整數類型,因此無法完成類內的初始化。我怎樣才能解決這個問題,而不限制類專業化。任何幫助表示讚賞。

+0

「在標題內部初始化類型將導致它被多次初始化。」你能否舉一個例子來說明你如何去做?如果您只是檢查構造函數是否被多次調用,則應該多次調用該構造函數,因爲每個模板類實例化都有一個成員。 – hvd 2012-01-08 20:02:34

回答

3

我不確定你的意思是「初始化cpp內部的類型會產生鏈接器錯誤。」但假設你實際上的意思是定義爲那麼你必須做錯了什麼,因爲在適當的位置爲每種類型定義靜態成員當然可行!你所擁有的類模板是一個對象的聲明,如果它曾經被引用過,這需要在某個地方定義。只有MyType碰巧是一個整數類型,你可以在你的類[template]中初始化它,並且你永遠不需要它的地址(例如綁定到一個常量引用或者它的地址),而不用定義它。這是因爲在這種情況下它始終被視爲一個常量表達式。

我的猜測是,你試圖定義一些CPP文件的對象是這樣的:

template <typename T> MyType const MyClass<T>::Type = some-initialization-here; 

這是行不通的,除非你也是在同一翻譯單元或隱或顯實例化這個定義。您可以定義成員的特定類型是這樣的:

template <> MyType const MyClass<T>::Type = some-initialization-here; 

除非你真正需要的類型是常量表達式在這種情況下,你通常可以側步的問題,如果有必要通過成爲一個enum (這是我傾向於這樣做,因爲這傢伙可以綁定到const參考無需定義),您可以使用它可以在頭部,而不是被定義靜態成員函數:

template <typename T> 
MyType const& MyClass<T>::Type() { 
    static MyType rc = some-initialization-here; 
    return rc; 
} 

BTW,我嗯非常確定這個問題之前回答,絕對在comp.lang.c++.moderated

+0

請注意,該函數仍然會導致'MyClass'包含多個'MyType'對象。除此之外,+1。功能本地靜力學優於類本地或全局靜力學,僅僅因爲你沒有靜態的初始化順序而失敗。 – Xeo 2012-01-08 21:01:49

+0

@Xeo:好的,確定:每個實例化一個對象。如果你不想要這個,你需要將靜態成員放入一個普通的[非模板化]基類中。 – 2012-01-08 21:37:30

1

初始化標題內部的類型會導致它多次初始化。

嗯,當然。一次爲MyClass實例化的每種不同類型。對於每種類型而言,這也是一個不同的對象,這與模板的工作方式有關。如果你只希望它定義並初始化一次,把它放在一個非模板庫:

namespace detail{ 
class MyClassBase{ 
protected: 
    ~MyClassBase(){} // only usable as a base class, non-polymorphic 
    static const MyType Type; // only available to derived types 
}; 
} // detail:: 

template<class T> 
class MyClass 
    : private detail::MyClassBase // private, non-polymorphic 
{ 
public: 
    using MyClassBase::Type; // if you want to expose 'Type' to the public audience 
}; 

現在,你可以把

const MyType detail::MyClassBase::Type = /*initialize here*/; 

在一個.cpp,並用它做。


注意,它一般會是更好的封裝static對象在函數內部,作爲@Dietmar所示。這些函數本地靜態優於任何其他類型的靜態對象,因爲在使用它們時不會遇到靜態初始化順序失敗。