1

I'm currently using the following simple singleton class:

template<class T>
class singleton
    : boost::noncopyable
{
public:
    static T& get_instance()
        {
            assert(sm_instance != nullptr);
            return *static_cast<T*>(sm_instance);
        }

protected:
    singleton()
        {
            assert(sm_instance == nullptr);
            sm_instance = this;
        }
    virtual ~singleton()
        {
            assert(sm_instance != nullptr);
            sm_instance = nullptr;
        }

private:
    static singleton<T>* sm_instance;
};

template<class T> singleton<T>* singleton<T>::sm_instance = nullptr;


class example_one
    : public singleton<example_one>
{
    static example_one instance;
};

example_one example_one::instance;


class example_two
    : singleton<example_two>
{
    static example_two instance;
};

example_two example_two::instance;


// Usage:
example_one& x = example_one::get_instance();
example_two& y = example_two::get_instance();   // not accessible because 'example_two' uses 'private' to inherit from 'singleton<T>'

However, I would like to tweak some things. I don't like that get_instance() is inherited to the derivative class.

I would like to do something like this (non-working code):

template<class T>
T& get_singleton();

template<class T>
class singleton
{
    friend T& get_singleton()
        {
            assert(sm_instance != nullptr);
            return *static_cast<T*>(sm_instance);
        }   
}

// Usage:
example_two& x = get_singleton<example_two>();
0xbadf00d
  • 17,405
  • 15
  • 67
  • 107
  • If you can avoid it in any way, don't use singletons - http://stackoverflow.com/questions/1392315/problems-with-singleton-pattern – Joris Timmermans Oct 20 '11 at 09:14
  • Your code makes not much sense. The first example checks if its instance field is null, in the CONSTRUCTOR (why?), and then the destructor is even worse. Your destructor should either delete sm_instance, or the destructor is not needed at all. Also setting an instacne field inside of a destructor to null, is completely pointless. – Angel O'Sphere Oct 20 '11 at 14:44
  • @AngelO'Sphere - I think you should read the code again and think about it. – 0xbadf00d Oct 20 '11 at 14:48

2 Answers2

0

If you are going to use a template function why bother with the base class:

template<typename T>
T& getInstance()
{
     static T  instance;
     return instance;
}

class example_one: boost::noncopyable
{
       example_one() {}  // Note private construtor
       friend example_one& getInstance<example_one>();
};

class example_two: boost::noncopyable
{
       example_two() {}
       friend example_two& getInstance<example_two>();
};
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • This is less flexible then my approach. You need a `friend` declaration, a private copy constructor and assignment operator and you cannot pass a compile time constant to the constructor of a `class`. – 0xbadf00d Oct 20 '11 at 09:09
  • No I would not do this either (as you are not going o find singeltons in my code). But your arguments are all flawed. 1) Its a singelton you don't need to pass anything to constructors there is only one thus all your initialization is done in the constructor you don't need to pass anything. 2) private constructor/copy constructor and assignment operator are needed for all singeltons. 3) My class has 1 line of extra code a friend. You defined a needless boiler plate subclass. I think you will find my neater and more maintainable. Even if singeltons is a completely bad idea to start with. – Martin York Oct 20 '11 at 09:30
  • If I was going to build a singleton I would use the classic Myers Singleton. I did it this way because you were trying to generalize the boilerplate. – Martin York Oct 20 '11 at 09:33
0

The solution popularized by Andrei Alexandrescu uses a different technique, which has several benefits compared to this one ( one of which is the tweak you want to make ). It's available at http://loki-lib.cvs.sourceforge.net/loki-lib/loki/include/loki/Singleton.h?view=markup , but you probably want to download the whole library ( loki ), or clean it up a bit if you don't need the extras. The interface then becomes:

typedef Loki::SingletonHolder&lt SomeType > SomeTypeSingleton;
SomeTypeSingleton::Instance(); // Access the single instance
Ylisar
  • 4,293
  • 21
  • 27