2013-10-13 41 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)

相关问题