Avatar of forums_mp
forums_mp
 asked on

Singleton template / private constructor for Singleton instances

Referencing the source below, I'm trying to prevent the case where the end user can create an instance of foo without utilzing Singleton::Instance.  IOW:  I"m trying to prevent this:
  foo f;
To do this I thought about making the constructor of foo protected but that's problematic for the singleton class.  I'm not sure how to achieve the objective without making foo a friend of Singleton which is not acceptable.  How can I achieve my objective?
# include <iostream>
# include <numeric>

template <typename T>
class Singleton
{
  //friend class foo; //not acceptable
protected:
   Singleton() {}
   virtual ~Singleton() {}
public:
   static T& Instance() 
   {
     static T obj ; 
     return ( obj ) ;
   }
private:
   Singleton(const Singleton &s);
   Singleton &operator = (const Singleton &s);
};

class foo : public Singleton < foo > 
{
  int x ; 
protected:
  //foo() {}
public :
  void SetX ( int const in ) 
  { x = in ; }
  int GetX () const { return ( x ) ; }
};

int main() 
{
  foo f; 
  f.SetX ( 5 ) ;
  foo& ff = foo::Instance();
  std::cout << ff.GetX() << std::endl;
  std::cin.get();
}

Open in new window

C++

Avatar of undefined
Last Comment
evilrix

8/22/2022 - Mon
js-profi

if you derive from singleton class you need to make the baseclass constructors protected or you couldnt create any instance.

why do want derive from singleton class? actually it is some contradiction cause for any derived class you may have one instance. so the baseclass isnt a singleton anymore.
js-profi

you make a singleton class by private constructor and providing a static instance of the class (the one and only instance). for example that way

class singleton
{
     singleton() {}
public:
     static singleton & Singleton()
     {
           // make a static instance
           static singleton s;
           return s;
     }
};

you then can access the singleton by Singleton()

 
js-profi

sorry it is

    singleton::Singleton()
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
evilrix

saif Al Islam

Just expanding on evilrix below example should give u what u exactly need
http://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton-Pattern-Part-2/3/
forums_mp

ASKER
evilrix:
I'm certainly no expert but I think I get the gist of the Myers singleton.  IOW I understand that.  My dilema reflected in the code below is this.  Now using the code reflected in the link provided by saifzahur, The end user could create an instance of the MyClass via:
McClass Mc ;
as shown in main.  I dont _want_ that.  If I make the MyClass constructor protected I get an error.  That's the issue.  The _one_ solutoin I could come up with is to declare MyClass a friend of the Singleton but that's undesirable.
# include <iostream>

// This is how a Gamma Singleton would instantiate its object.
template <class T> struct CreateGamma {
  static T* Create() { return new T; }
};

// This is how a Meyers Singleton would instantiate its object.
template <class T> struct CreateMeyers {
  static T* Create() {
    static T _instance;
    return &_instance;
  }
};

// This Singleton class accepts different creation policies.
template <class T, template<class> class CreationPolicy=CreateMeyers>
class Singleton {
public:
  static T& Instance() {
    if (!m_pInstance)
      m_pInstance=CreationPolicy<T>::Create();
    return *m_pInstance;
}

private:
  Singleton();            // ctor hidden
  ~Singleton() { std::cout << "l" << std::endl; }           // dtor hidden
  Singleton(Singleton const&);    // copy ctor hidden
  Singleton& operator=(Singleton const&);  // assign op hidden

  static T* m_pInstance;
};
template <class T, template<class> class C> T* Singleton<T,C>::m_pInstance=0;

class MyClass {
  int xx ;

public: 
  MyClass()    
   : xx ( 0 )
  {}
  void foo ( int x ) 
  { 
    xx = x; 
    std::cout << "MyClass::foo(" << std::hex << xx << ") called" << std::endl; 
  }
  int bar() 
  { 
    std::cout   << "MyClass::bar called" <<  std::endl; 
    return ( xx ) ; 
  }
  ~MyClass () 
  { std::cout << "~MyClass::MyClass" << std::endl; }
};

typedef Singleton<MyClass, CreateGamma> MyClassLeaking;
void test3()
{
  int val=MyClassLeaking::Instance().bar();
  MyClassLeaking::Instance().foo(++val);
  MyClassLeaking::Instance().bar();
}
typedef C_Singleton< lets_see > LetsSeeInstance; 


int main() {
  MyClass mC ; 
  std::cout << "using leaking singleton"  << std::endl; 
  MyClassLeaking::Instance().foo(0x0100);
  std::cout << "test3"  << std::endl; 
  test3();
  std::cout << "test3"  << std::endl; 
  test3();
  //std::cin.get();
}

Open in new window

⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ASKER CERTIFIED SOLUTION
evilrix

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
forums_mp

ASKER
evilrix: Two questions
a) Did you mean return new CreateGamma as opposed to new  T as reflected below?
b) The class implies that something amiss about the code with the reference to "leaking'.  I'm not sure if I'm seeing anything wrong per se besides the fact that MyClass desctructor is never called.  NOTE: I'm referencing the code posted at ID: 26712359   (with your MyClass destructor _IS_ called - a good thing). Of course you were using 'CreateGamma'
// This is how a Gamma Singleton would instantiate its object. 
template <class T> struct CreateGamma : T { 
  static T* Create() { return new CreateGamma; } 
}; 

Open in new window

SOLUTION
evilrix

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
forums_mp

ASKER
evilrix:  Excellent!  Thanks.. I'm all set again.
evilrix

>> Excellent!  Thanks.. I'm all set again.
You are very welcome. If you have any more questions please don't hesitate to post back here.
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy