Alcott
Alcott

Reputation: 18585

how to implement Singleton in C++

This post is what I just read.

The way he implements Singleton in C++ confuses me. I got several Questions about it and here is his code:

template<typename T>
class Singleton {
public:
    static T& getInstance() {  //Question 1
        return instance;
    }
private:
    static T instance;
};

class DebugLog : public Singleton<DebugLog> {  //Question 2
public:
    void doNothing() {}
};

Question

  1. I think we should put the static T& getInstance()'s definition outside of the class body, right?

  2. He tries to make class DebugLog a singleton class, but when he inherits Singleton<DebugLog>, the DebugLog doesn't already exist, right? If right, then how can the template class Singleton instantiate an un-existent class?

Upvotes: 0

Views: 751

Answers (3)

James Kanze
James Kanze

Reputation: 153919

  1. It would certainly be cleaner if the function were defined outside of the class, and make the code easier to read and to maintain. In this case, however, the complete class is small enough that the difference isn't very great, and of course, because we're dealing with a template, the actual definition still has to be included in every translation unit which uses it.

The C++ standard doesn't speak of “existence” with regards to classes (or anything else). At the point of template instantiation, name lookup finds DebugLog, and finds that it is a class (thus, a type). At that point, it is an incomplete type, and there are only limited things you can do with an incomplete type. If the class template which is instantiated doesn't do anything that requires a complete type (and Singleton doesn't), then there is no problem. (Note that only the class definition is instantiated at this point; class member functions will not be instantiated until they are used.)

I might add that there is still one important thing missing from the code you posted: there is no definition for the declaration Singleton::instance. You still need to add a:

template<typename T> T Singleton<T>::instance;

somewhere.

Upvotes: 1

Kerrek SB
Kerrek SB

Reputation: 477040

1) Nope, it doesn't matter how you structure your code. Singleton isn't a class, by the way: It's a template. Since the full template definition must be visitible at any instantiation site anyway, you might as well define everything inline.

2) class DebugLog : public Singleton<DebugLog> is fine. We are not inheriting from a non-existing class; rather, we are inheriting from the class Singleton<DebugLog>. Templates can be instantiated on incomplete types. (There are several rules what you can and cannot do with such a type parameter.)

For example, template <typename T> class Foo { }; can certainly be instantiated on any type without problem. More interestingly, template <typename T> struct PointerFactory { typedef T * type; }; can be instantiated on any type, complete or not. In the present situation, the purpose of the template parameter in the CRTP is solely to inform the base class of its eventual derived type, so this is entirely fine.

Upvotes: 5

Tio Pepe
Tio Pepe

Reputation: 3089

You must use a pointer to T in this case:

template<typename T>
class Singleton {
public:
    static T& getInstance() {
        static T * instance = NULL;
        if (!instance)
            instance = new T;
        return *instance;
    }
};

class DebugLog : public Singleton<DebugLog> {  //Question 2
    public:
        void doNothing() {}
};

Upvotes: -3

Related Questions