[ACCEPTED]-Singleton and Abstract base class in C++-singleton

Accepted answer
Score: 10

You'd want to use something like

IFoo my_foo = Singleton<Foo>::Instance();
my_foo->foo();

Basically 7 you'll have to instantiate the template 6 Singleton using a concrete class (in this 5 case, your class Foo) and given that your 4 Foo derives from IFoo you can refer to it 3 through a base pointer. You cannot directly 2 instantiate a template using an incomplete 1 or abstract class.

Score: 8

You can't do this. IFoo is an interface, by 4 design and definition. The number of instances 3 is therefore 0. On the other hand, the definition 2 of a singleton class is that you have 1 1 instance. 0 != 1.

Score: 2

You can always do something like this:

class IFoo {};
class Foo : public IFoo {};

template <typename T>
class Singleton
{
    // ..
};

typedef Singleton<Foo> FooSingleton;

int main()
{
    FooSingleton::Instance()->foo();

    return 0;
}

0

Score: 1

The annoying meta-answer is, "why are 6 you using a singleton?" I have yet 5 to find a situation where you really need to use 4 it. IMHO its drawbacks outweigh its advantages, in 3 real life situations that is.

Using something 2 like 'boost::noncopyable' might be what 1 you are after.

See this post for more info

Score: 1

Here is another possible solution I found 6 that works nicely.

Add this to Singleton:

#ifndef ABSTRACT_CLASS
    static T* D()
    {
        return new T();
    }
#else
    static T* D()
    {
        return NULL;
    }
#endif

static T* Instance( T*(*func)() )
{
    if( !m_instance )
    {
        m_instance = func();
    }

    return m_instance;
}

static T* Instance()
{
    if( !m_instance )
    {
        m_instance = D();
    }

    return m_instance;
}

Ensure 5 the abstract class is in a header, while 4 the implementations are in sources.

For example:

// IFoo.h
//
#define ABSTRACT_CLASS

class IFoo
{
    virtual ~IFoo() {}

    virtual void SomeFunc() = 0;
};

extern IFoo* BuildFoo();


// Foo.cpp
//
#include "IFoo.h"

class Foo : public IFoo
{
    Foo() {}
    ~Foo() {}

    void SomeFunc() {}
};

IFoo* BuildFoo() { return new Foo(); }

With 3 these additions, you can now do the following:

IFoo::Instance( BuildFoo );

IFoo::Instance()->SomeFunc();

Just 2 remember to #define ABSTRACT_CLASS in the 1 header for every abstract class.

Score: 1

I've encountered the same problem recently.

It can be implemented with 4 what I know as gem singleton. It using assert for forcing uniqueness 3 and Curiously recurring template pattern for calling interface implementation 2 via singleton:

template <typename T>
class Singleton {
 public:
  Singleton(const Singleton<T>&) = delete;
  Singleton& operator=(const Singleton<T>&) = delete;       
  Singleton() {
    assert(!msSingleton);
    msSingleton = static_cast<T*>(this);
  }
  ~Singleton(void) {
    assert(msSingleton);
    msSingleton = 0;
  }
  static T& getSingleton(void) {
    assert(msSingleton);
    return (*msSingleton);
  }
 protected:
  static T* msSingleton; 
};    

class IFoo : public Singleton<IFoo> {    
 public:
  virtual void foo() = 0;
};

class FooImpl : public IFoo {
 public:
  FooImpl();
  void foo() override { std::cout << "FooImpl::foo()\n"; }
};

template <>
IFoo* Singleton<IFoo>::msSingleton = 0;

FooImpl::FooImpl() { msSingleton = this; }

After manually instantiating 1 FooImpl, call of IFoo::getSingleton().foo() will call FooImpl's code.

int main() {
  FooImpl f;
  IFoo::getSingleton().foo();
}

demo

Score: 0

Look at it like this: There is nothing in 8 your program that would tell the compiler 7 which implementation of the IFoo interface 6 it should be instantiating. Remember, there 5 could be other implementations besides Foo.

If 4 you want to use a class via an interface 3 and define which actual implementation shall 2 be used somewhere else, take a look at the 1 Abstract Factory pattern.

Score: 0

I had to do something similar to add unit 9 tests to some legacy code. I had to replace 8 an existing singleton which used a template. I 7 gave two parameters to the singleton template, the 6 first is the interface the second is the 5 implementation.

However I also had to add 4 a setTestInstance method to enable the unit tests override 3 the instance at runtime.

template <typename IfaceT, typename ImplT>
class Singleton
{
public:
   static IfaceT* Instance() {
      if (m_instance == NULL) {
         m_instance = new ImplT();
      }
      return m_instance;
   }

   // Only used for unit tests 
   // Takes ownership of instance
   static void setTestInstance(IfaceT* instace) {
      m_instance = instance;
   }
private:
   static IfaceT * m_instance;
};

In this case setTestInstance should 2 use a std::auto_ptr and m_instance should be a boost::scoped_ptr. To avoid memory 1 leaks.

Score: 0

I think the best solution would be to introduce 2 a factory class or method here. Just imagine 1 the following:

struct FooCreator
{
  typedef IFoo*     result_type;

  result_type operator()()const
  {
     return new Foo;
  }
};

template<class Factory>
struct Singleton
{

  static typename Factory::result_type instance()
  {
    if(instance_==typename Factory::result_type())
      instance_ = Factory()();
    return instance_;
  } 

private:
  Singleton(){};

  static typename Factory::result_type instance_;
};

template<class F>
typename F::result_type Singleton<F>::instance_ = typename F::result_type();

Best Regards,
Ovanes

More Related questions