Generic vs Solid Singletons: hiding dtor issue

Hi there,
I have a generic Singleton which works fine:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <class T>
class Singleton
{
public:
  static T& Instance() {
    static T _instance;		
    return _instance;
  }
private:
  Singleton();          
  ~Singleton(); // dtor hidden:OK
  Singleton(Singleton const&);
  Singleton& operator=(Singleton const&);
};


but with the following solid Singleton, I can not hide the dtor:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Singleton {
private:
	static Singleton s;
	int i;
	Singleton(int x) : i(x) {};
	~Singleton();// hiding dtor does not link
	Singleton& operator=(Singleton&); 
	Singleton(const Singleton&);	  
public:
	static Singleton& instance() { return s;}
	int getValue() { return i; }
	void setValue(int x) { i = x; }
};

Singleton Singleton::s(47);


Why can not I hide the dtor in the solid version of Singleton? Thanks.
Last edited on
I need to look more closely at this part:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <class T>
class Singleton
{
public:
  static T& Instance() {
    static T _instance;		
    return _instance;
  }
private:
  Singleton();          
  ~Singleton(); // dtor hidden:OK
  Singleton(Singleton const&);
  Singleton& operator=(Singleton const&);
}; 

- it doesn't seem right - it looks like a Singleton object isn't actually created.
Assuming the generic template Singleton (questqulkan quoted above) is declared in “singleton.h”,here is how it would be used / tested:
http://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton-Pattern-Part-2/2/
Let's look again at the solid Singleton: I changed the private dtor of Singleton from declaration [ ~Singleton();] to an empty implementation[ ~Singleton() { }] on line 6:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Singleton {
private:
	static Singleton s;
	int i;
	Singleton(int x) : i(x) {};
	~Singleton() {};// now it is NOT: ~Singleton();
	Singleton& operator=(Singleton&); 
	Singleton(const Singleton&);	  
public:
	static Singleton& instance() { return s;}
	int getValue() { return i; }
	void setValue(int x) { i = x; }
};

Singleton Singleton::s(47);


and it compiles. I guess that the original version does not link because we have defined a private ctor that takes an int as the parameter. Should we want to use a dtor of our own, we must give a full implementation of it, or use the default one that the compiler generates. The original code does not link because it tried to define a dtor, but give no implementation of it. This would lead to no default dtor being generated by compiler, nor we give one for it. Then the Singleton class has a ctor, but no dtor: problem. (BTW: the code compiles if line 6 is commented out = the default one that the compiler generates is used .)

Is this the real cause of the link issue originally reported? Thanks.
Last edited on
Coming back to my original issue:
Looking at the two different of code in your original post - there are fundamentally different.
If you look closely at the first few lines of the template version, you will see this:

1
2
3
4
5
6
7
8
 template <class T>
class Singleton
{
public:
  static T& Instance() {
    static T _instance;		
    return _instance;
  } 


Note very carefully that the Instance function does NOT create/return a reference object of type Singleton.
It returns an object of whatever type you create create the template with.
For example:
1
2
3
 //some code
#include <string>
Singleton<string> myVar(6); 


then:
myVar::Instance() will return a reference to a string
So no object of type Singleton has been created, so the Singleton destructor is not used and as it is a template, the destructor code is not even instantiated by the compiler, so
there is no issues with the destructor


HOWEVER:
For the non - template code you have:

1
2
3
4
5
 class Singleton {
private:
	static Singleton s;
	int i; 

As you can see an object of type Singleton is actually created (s).



So for the two set of codes to be the same, the template class should look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <class T>
class Singleton
{
public:
  static Singleton& Instance() {
    static Singleton _instance;	    
    return _instance;
  }
 
private:
 
  Singleton() {};        
  ~Singleton(){};
  Singleton(Singleton const&);
  Singleton& operator=(Singleton const&);
}; 



PS - you edited your code.
I'll have a look at that link you posted later.
So far I have just used the generic and solid Singletons separately. guestgulkan's discussion leads to make them identical. I am reading the post very carefully: it is a very interesting topic!
Last edited on
Topic archived. No new replies allowed.