2013-10-13 71 views
2

我有一個模板單例類,有一個靜態實例和一個靜態getInstance()方法。但是,我收到來自g ++(MinGW)的實例的未定義​​參考錯誤;起初,我認爲這是鏈接器順序錯誤,但無論我把它放在哪個順序中,我都可以得到相同的結果。模板類的靜態成員沒有實例化,除非明確專用?

但是,我發現如果我明確地專門化實例,它會編譯(這是「可接受的解決方案)。所以,這裏是代碼:

Singleton.hpp:

#ifndef SINGLETON_HPP 
#define SINGLETON_HPP 

#include <iostream> 

template<int X=100> 
class Singleton { 
protected: 
    static Singleton<X> *instance; 
public: 

    static Singleton<X>& getInstance() { 
     if(!Singleton<X>::instance) { 
      Singleton<X>::instance = new Singleton<X>(); 
     } 
     return *Singleton<X>::instance; 
    } 

    void foo() { 
     std::cout << "Test<" << X << ")::foo()" << std::endl; 
    } 
}; 

#endif 

Singleton.cpp:

#include "Singleton.hpp" 

template<int X> 
Singleton<X>* Singleton<X>::instance = NULL; 

#ifdef SPECIALIZE 
template<> 
Singleton<100>* Singleton<100>::instance = NULL; 
#endif 

Main.cpp的:

#include "Singleton.hpp" 

int main(int ac, char *av[]) { 
    Singleton<100> &sing = Singleton<100>::getInstance(); 
    sing.foo(); 
} 

那麼這裏的三種不同的方式編譯和輸出:

沒有專業化,SingletonMain.o聯第一:

C:\Test>g++ -c Singleton.cpp 

C:\Test>g++ -c SingletonMain.cpp 

C:\Test>g++ -o Singleton.exe SingletonMain.o Singleton.o 
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x7): undefined reference to `Singleton<100>::instance' 
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x1c): undefined reference to `Singleton<100>::instance' 
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x21): undefined reference to `Singleton<100>::instance' 
collect2: ld returned 1 exit status 

沒有專業化,Singleton.o聯第一:

C:\Test>g++ -c Singleton.cpp 

C:\Test>g++ -c SingletonMain.cpp 

C:\Test>g++ -o Singleton.exe Singleton.o SingletonMain.o 
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x7): undefined reference to `Singleton<100>::instance' 
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x1c): undefined reference to `Singleton<100>::instance' 
SingletonMain.o:SingletonMain.cpp:(.text$_ZN9SingletonILi100EE11getInstanceEv[Singleton<100>::getInstance()]+0x21): undefined reference to `Singleton<100>::instance' 
collect2: ld returned 1 exit status 

專業化:

C:\Test>g++ -DSPECIALIZE -c Singleton.cpp 

C:\Test>g++ -DSPECIALIZE -c SingletonMain.cpp 

C:\Test>g++ -DSPECIALIZE -o Singleton.exe Singleton.o SingletonMain.o 

現在,似乎是有人在這裏有類似的問題 - C++ template static member instantiation - 但「解決方案」是有明確的專業化每種類型,你可能會使用...這似乎總數最終打敗模板的目的...所以必須有更好的方法,對吧?

回答

1

您必須將靜態成員定義移動到標題。與所有其他模板一樣,類模板的靜態成員的定義必須出現在使用它的每個翻譯單元中。這基本上意味着它屬於標題。

引用C++ 11,[temp]§6

函數模板,類模板或模板類的靜態數據成員的成員函數,應在每一個轉換單元中定義,其中它是隱式實例化(14.7.1),除非相應的特化在某些翻譯單元中被明確實例化(14.7.2);不需要診斷。

(Emphasis mine)

相關問題