Линкер в некоторых случаях жалуется на неопределенный реф.к члену статического объекта класса шаблона - PullRequest
0 голосов
/ 31 мая 2018

Я новичок в шаблонном программировании.При реализации одноэлементного класса с использованием шаблона я обнаружил, что в некоторых случаях (как показано ниже) компоновщик жалуется на ошибку:

undefined reference to `Singleton<Test>::_lock'

Однако, если я изменю следующий оператор

template<> Mutex Singleton<Test>::_lock;

на

template<> Mutex Singleton<Test>::_lock(1);

компилируется и запускается без ошибок.

Может ли кто-нибудь помочь мне и объяснить, почему в приведенном ниже случае сбой компиляции?

#include <iostream>
#include <pthread.h>

class Mutex {
public:
    Mutex(){ pthread_mutex_init(&mMutex, NULL); }
    Mutex(int dummy){ pthread_mutex_init(&mMutex, NULL); }
    ~Mutex(){ pthread_mutex_destroy(&mMutex); }
    Mutex(const Mutex&) = delete;
    Mutex&      operator = (const Mutex&) = delete;

    int lock(){ return -pthread_mutex_lock(&mMutex); }
    void unlock(){ pthread_mutex_unlock(&mMutex); }

    // Manages the mutex automatically. It'll be locked when Autolock is
    // constructed and released when Autolock goes out of scope.
    class Autolock {
    public:
        explicit Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
        ~Autolock() { mLock.unlock(); }
    private:
        Mutex& mLock;
    };

private:
    pthread_mutex_t mMutex;
};

template <typename T>
class Singleton: {
public:
    static T& Instance() {
        Mutex::Autolock _l(_lock);
        if(nullptr == _instance) {
            _instance = new T();
        }

        return *_instance;           
    }
    virtual ~Singleton(){}
    Singleton() = default;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    static T* _instance;
    static Mutex _lock; 
};


class Test: public Singleton<Test> {
public:
    void dis() {std::cout << "hi" << std::endl;}

};

template<> Mutex Singleton<Test>::_lock;
template<> Test* Singleton<Test>::_instance(nullptr);
template class Singleton<Test>;

int main()
{
    Test::Instance().dis();    
    return 0;    
}
...