Search code examples
c++templatesdefinitiontemplate-specializationexplicit-specialization

C++: specializing member requires template<> syntax


I am trying the following...

#include <iostream>

using namespace std;

template<class T>
class Singleton
{
private:
    class InstPtr
    {
    public:
        InstPtr() : m_ptr(0) {}
        ~InstPtr() { delete m_ptr; }
        T* get() { return m_ptr; }
        void set(T* p)
        {
            if (p != 0)
            {
                delete m_ptr;
                m_ptr = p;
            }
        }
    private:
        T* m_ptr;
    };

    static InstPtr ptr;
    Singleton();
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);

public:
    static T* instance()
    {
        if (ptr.get() == 0)
        {
            ptr.set(new T());
        }
        return ptr.get();
    }
};

class ABC
{
public:
    ABC() {}
    void print(void) { cout << "Hello World" << endl; }
};

When I am trying to do the following in visual studio, it works fine.. But when I compile using g++, it fails with specializing member ‘Singleton<ABC>::ptr’ requires ‘template<>’ syntax. What I am missing here?

#define ABCD (*(Singleton<ABC>::instance()))
template<> Singleton<ABC>::InstPtr Singleton<ABC>::ptr;
Singleton<ABC>::InstPtr Singleton<ABC>::ptr;

int main(void)
{
    ABCD.print();
    return 0;
}

Solution

  • Singleton<ABC>::InstPtr Singleton<ABC>::ptr;
    

    should be used for defining the static member of a explicitly specialized class template, e.g.

    template<class T>
    class Singleton
    {
        ...
    };
    
    // explicit specialization
    template<>
    class Singleton<ABC>
    {
    private:
        class InstPtr
        {
            ...
        };
    
        static InstPtr ptr;
        
        ...
    };
    
    Singleton<ABC>::InstPtr Singleton<ABC>::ptr; // definition of the static member
    

    LIVE


    And, the explicit specialization of a static data member like

    template<> Singleton<ABC>::InstPtr Singleton<ABC>::ptr;
    

    is a declaration, but not a definition.

    You need to specify initializer for it, e.g.

    template<> Singleton<ABC>::InstPtr Singleton<ABC>::ptr{}; // definition of the static member
    

    LIVE

    An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. These definitions must use braces for default initialization:

    template<> X Q<int>::x; // declaration of a static member
    template<> X Q<int>::x (); // error: function declaration
    template<> X Q<int>::x {}; // definition of a default-initialized static member