Static member of template class not instantiated unless explicitly specialized?

拟墨画扇 提交于 2020-01-04 13:46:07

问题


I have a template singleton class, with a static instance, and a static getInstance() method. However, I'm getting an undefined reference error on the instance from g++ (MinGW); at first, I thought it was linker-order error, but I get the same thing no matter which order I put them in.

However, I found that if I explicitly specialize the instance, it does compile (which isn't an acceptable solution). So, here's the code:

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();
}

Then here's the three different ways of compiling, and the output:

No specialization, SingletonMain.o linked first:

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

No specialization, Singleton.o linked first:

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

With specialization:

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

Now, there does seem to be someone having a similar problem here -- C++ template static member instantiation -- but the "solution" was to have an explicit specialization for each type you might use...which seems to totally defeat the purpose of templates...so there has to be a better way, right?


回答1:


You must move the static member definition to the header. Just like with everything else templated, a definition of a static member of a class template must be present in every translation unit where it's used. This basically means it belongs into the header.

Quoting C++11, [temp]§6:

A function template, member function of a class template, or static data member of a class template shall be defined in every translation unit in which it is implicitly instantiated (14.7.1) unless the corresponding specialization is explicitly instantiated (14.7.2) in some translation unit; no diagnostic is required.

(Emphasis mine)



来源:https://stackoverflow.com/questions/19347671/static-member-of-template-class-not-instantiated-unless-explicitly-specialized

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!