|
-
October 1st, 2010, 08:45 PM
#1
Other implementation of singleton
For a class that has an explicit constructor with 2 parameters, I'm thinking to rewrite my Singleton. This idea is because the "getInstance()" method of Singleton. If the implementation of this method is like this:
Code:
static Singleton<T>::_instance = NULL;
template <typename T>
template <typename U, typename X >
T* Singleton<T>::getInstance( U, X )
{
if( _instance == NULL )
_instance = new T( U, X );
return _instance;
}
Every time I call getInstance, I need to pass parameters. For the first time it's ok, but for another calls it's not fine to do this.
Code:
class MyClass : public Singleton<MyClass>
{
public:
explicit MyClass( int, char );
...
}
But if I have a Singleton that receives the parameters and verifies inside their constructor, I think it works.
Code:
template< typename T >
class Singleton
{
public:
template <typename X, typename U>
Singleton()
{
if( _instance == NULL )
{
_instance = new T( X, U );
}
T* getInstance()
{
return _instance;
}
}
private:
static T* _instance;
};
Ok, the problem for me is, is a good way to solve the explicit parameters in constructor with this solution? Is there a better way to do?
Any help is very appreciated.
Thanks
Last edited by C#er; October 3rd, 2010 at 03:10 PM.
Reason: Error in code tag
-
October 1st, 2010, 10:10 PM
#2
Re: Other implementation of singleton
Singleton has nothing to do with templatized problems
As soon as you don't use a static private member in the class itself but still are able to make your class a singleton, then it is a new implementation
-
October 2nd, 2010, 03:14 AM
#3
Re: Other implementation of singleton
How can a singleton take any parameters? The entire point is that there is only one, and hence, passing parameters goes against the design.
Unless you plan to do a singleton_family design, where you can call "getInstance(X,Y)", but in this case, you would have a different object for each X,Y pair. That is another approach, but right now, you don't seem to be doing either.
Plus, you are throwing template parameters in there that have no reason to be. What exactly do you want to do, in english?
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
-
October 2nd, 2010, 09:25 AM
#4
Re: Other implementation of singleton
Like I explained before, what I DON'T want to do is to have a getInstance(X, U) method for the reasons you pointed, dodra.
My intent is, instead the constructor with parameter of my singleton to be private, I leave it public, passing proper parameters. When I get its instance, I call getInstance(), passing no parameters because the object was initialized before. For me this is a clean way.
And yes, the first piece of code there are no reason to be template parameters, it's just a sample of what I don't want to do.
All of this is because I have a class with a explicit constructor with parameters.
I want this class to be transformed in a Singleton, ok?
-
October 2nd, 2010, 09:53 AM
#5
Re: Other implementation of singleton
 Originally Posted by C#er
Like I explained before, what I DON'T want to do is to have a getInstance(X, U) method for the reasons you pointed, dodra.
monarch_dodra point is that such a "singleton with parameters" is not a singleton from a design pattern point of view.
 Originally Posted by C#er
When I get its instance, I call getInstance(), passing no parameters because the object was initialized before. For me this is a clean way.
Indeed, given a getInstance() call how can you be sure that getInstance(<with parameters>) has already been called before ( exactly once ) ? if you do so you defeat the very purpose of the pattern ...
-
October 2nd, 2010, 09:56 AM
#6
Re: Other implementation of singleton
 Originally Posted by C#er
My intent is, instead the constructor with parameter of my singleton to be private, I leave it public, passing proper parameters. When I get its instance, I call getInstance(), passing no parameters because the object was initialized before. For me this is a clean way.
If you leave the constructor public, than there's no singleton - any client code can create more than one instance. The purpose of the Singleton pattern is to prevent the creation of multiple instances by enforcing the users to obtain the only one that exists via GetInstance().
 Originally Posted by C#er
And yes, the first piece of code there are no reason to be template parameters, it's just a sample of what I don't want to do.
All of this is because I have a class with a explicit constructor with parameters.
I want this class to be transformed in a Singleton, ok?
Well, do you need templates or not, and if so, why?
If not, is are the types of the parameters that this constructor should take known? If the instances of these types that are created by their default constructor would do the trick, than you don't need to pass them as parameters at all.
Again, what exactly are you trying to do?
Maybe not all of the responsibility should belong to this class?
-
October 2nd, 2010, 10:03 AM
#7
Re: Other implementation of singleton
ah, I think I've got what C#er is trying to do:
so, you have a class template "Singleton" that you use to make "MyClass" a singleton, and you want to modify "T* Singleton::getInstance()" (that is, without parameters ) in a such way it automatically initializes MyClass when MyClass exposes an explicit ctor with two parameters, am I right ?
-
October 2nd, 2010, 10:25 AM
#8
Re: Other implementation of singleton
If you leave the constructor public, than there's no singleton - any client code can create more than one instance. The purpose of the Singleton pattern is to prevent the creation of multiple instances by enforcing the users to obtain the only one that exists via GetInstance().
I know about that. I suggest my implementation because I didn't find a way to create MyClass with parameters based on a Singleton. MyClass is just a sample. I have a real class that enforces the use of parameterized constructor and this class is used in lots of places of project. So I've think to use Singleton( a little bit modified ). I want to initialized MyClass once. That's it.
so, you have a class template "Singleton" that you use to make "MyClass" a singleton, and you want to modify "T* Singleton::getInstance()" (that is, without parameters ) in a such way it automatically initializes MyClass when MyClass exposes an explicit ctor with two parameters, am I right ?
Superbonzo, you are totally right.
Last edited by C#er; October 2nd, 2010 at 10:32 AM.
-
October 2nd, 2010, 12:00 PM
#9
Re: Other implementation of singleton
 Originally Posted by C#er
... you are totally right.
well, then, the simplest thing that comes to my mind given your requirements is (whatever your singleton implementation is):
Code:
// Singleton.h
template <class T> class SingletonTraits
{
static T* CoCreate() { return new T(); }
};
// ...
// the Singleton implementation will create T objects trough SingletonTraits<T>::CoCreate()
Code:
// in MyClass.h
class MyClass : public Singleton<MyClass>
{
public:
explicit MyClass(int,char);
}
template <> class SingletonTraits<MyClass>
{
static MyClass* CoCreate() { return new MyClass(0,'0'); }
};
in this way you don't need to touch pre-existing classes deriving from Singleton<T> ...
that said, I don't see the reason why you need to derive from a Singleton<T>; it would make more sense directly invoking the Singleton<T>::getInstance static method; in this way, you make clear that T is NOT a singleton (because it exposes a public ctor) ...
-
October 2nd, 2010, 03:09 PM
#10
Re: Other implementation of singleton
Of course, as long as there's a public constructor in MyClass, you can only hope that the users of the class will be disciplined enough not to use it directly. Ever.
But you can safely assume that any potential client code will break this rule... 
IMO, there's no point making a class behave as a singleton through the use of external helper methods/classes, when the possibility to create more than one instance still exists.
So C#er, I'll suggest something slightly different, maybe it will be useful for what you want to do.
If you consider MyClass to be a part of some system (let's call it Foo System - large or small, it doesn't matter), and MyClass also needs to be singleton-like, but the constructor requires the two parameters, you can create another class called FooSystem that would represent this conceptual system. You can then migrate the singleton-related functionality to this new class. FooSystem would actually store the only MyClass instance.
Then instead of requiring the client code to pass parameters to MyClass' constructor, you can now say that the clients need to initialize the system before it can be used.
The client code would call a one-time static initialization function, in a way similar to this:
FooSystem::Initialize(2, 'a'); FooSystem would, in turn, store these and use them when required.
The clients of your code must call this function before using the 'system'; failing to do so should result in an error.
Now, FooSystem should also have a static function GetMyClassInstance(), that would do the actual initialization if necessary. This function, or the FooSystem class, would be declared as friend in the MyClass class, so that the constructor of the latter can be made private. Like this, the only way to access the one instance of MyClass is via FooSystem::GetMyClassInstance().
Code:
class FooSystem
{
private:
static MyClass _myInstance;
static int _initInteger;
static char _initChar;
public:
static void Initialize(int, char); // sets _initInteger & _initChar...
static MyClass* GetMyClassInstance(); // calls MyClass' constructor if required, otherwise returns _myInstance
};
class MyClass
{
private:
MyClass(int, char);
//...
friend MyClass* FooSystem::GetMyClassInstance();
public:
//...
};
// ...
// Client code:
// Required one-time initialization, otherwise an error occurs
FooSystem::Initialize(2, 'a');
// Use the only instance
FooSystem::GetMyClassInstance()->DoSomething();
// and then later, again
FooSystem::GetMyClassInstance()->DoSomethingElse();
No templates here, because, if I understood the OP right, the only reason he (she?) introduced templates was because he/she tried to solve the problems related to the existence of the parametrized constructor.
>> NOTE: Since I'm less a C++-er and more of a C#-er myself ( ), I'll ask C++ experts here to point out any errors this code potentially has. Also, this approach could have drawbacks that I'm unaware of, so if anyone notices them, please tell.
Also, note that, depending on what exactly is the role of these parameters, it might be possible to omit them in the constructor (leave them uninitialized), and have the client code set and possibly change them later, if that's meaningful in the given context.
Last edited by TheGreatCthulhu; October 2nd, 2010 at 03:36 PM.
-
October 2nd, 2010, 04:40 PM
#11
Re: Other implementation of singleton
 Originally Posted by TheGreatCthulhu
Also, note that, depending on what exactly is the role of these parameters, it might be possible to omit them in the constructor (leave them uninitialized)
That's a bad idea. The best match-case was already provided by superbonzo, there's no need to break the fundamental rule of object instantiation for the sole purpose of passing two parameters to the ctor that could lead to buggy code.
The only thing that is missing from the specialization method example is that the arguments are hard-coded into the class and specializing itself might become a tedious work if there are many objects to be "singleton-ized", in which we can make the example code even more generic, something along the line of
Code:
namespace demo
{
template <typename T_> struct unary_impl;
template <typename T_> struct binary_impl;
template <typename T_, template <typename Tp_ = T_> class D_ = unary_impl>
struct unary_interface
{
typedef D_<T_>* impl_pointer_type;
template <typename X_>
unary_interface(const X_& x)
{
static_cast<impl_pointer_type>(this)->create(x);
}
private:
unary_interface(const unary_interface&);
unary_interface& operator=(const unary_interface&);
};
template <typename T_, template <typename Tp_ = T_> class D_ = binary_impl>
struct binary_interface
{
typedef D_<T_>* impl_pointer_type;
template <typename X_, typename Y_>
binary_interface(const X_& x, const Y_& y)
{
static_cast<impl_pointer_type>(this)->create(x, y);
}
private:
binary_interface(const binary_interface&);
binary_interface& operator=(const binary_interface&);
};
template <typename T_>
class unary_impl : private unary_interface<T_>
{
friend class unary_interface<T_>;
template <typename X_>
static void create(const X_& x)
{
if(m_ptr == 0)
m_ptr = new T_(x);
}
static T_* m_ptr;
unary_impl();
};
template <typename T_> T_* unary_impl<T_>::m_ptr(0);
template <typename T_>
class binary_impl : private binary_interface<T_>
{
friend class binary_interface<T_>;
template <typename X_, typename Y_>
static void create(const X_& x, const Y_& y)
{
if(m_ptr == 0)
m_ptr = new T_(x, y);
}
static T_* m_ptr;
binary_impl();
};
template <typename T_> T_* binary_impl<T_>::m_ptr(0);
} // end namespace demo
But of course, the idea of singleton itself does not deviate from the fact that it is just another way of controlling object creation. Using some sort of referencing counting is probablly the right choice for the OP, and if the need to make getInstance() is so frequent and is all over the project, I bet my lunch money that there's something wrong with the design of the application in the first place.
-
October 4th, 2010, 07:56 AM
#12
Re: Other implementation of singleton
Guy, thanks for your replies. It was very positive and I have a good idea of what I have to do.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|