Is it possible to define a Meyer's singleton (like this one) with arguments?
I know it is possible with the GOF style singleton (like here),
but I can't seem to make it work with Meyer's singletons:
// ...
public:
static S& getInstance()
{
static S instance; // no way to pass arguments here ...
return instance;
}
EDIT:
I want a single Init function, and multiple getInstance.
So a typical usage is something like:
S::Init(5, 6.4);
foo(S::getInstance());
bar(S::getInstance());
You can just store the initialization parameters in statics. Example:
class S {
public:
static void Init(int i)
{
i_ = i;
initialized_ = true;
}
static S& getInstance()
{
if (!initialized_) {
throw SomeException;
}
static S instance(i_);
return instance;
}
private:
S(int) { }
static int i_;
static bool initialized_;
};
Remember to actually define the statics in the implementation (.cpp) file:
int S::i_ = 0;
bool S::initialized_ = false;
Obviously you could use Meyer singletons as well for these, but since they're built-in types and do not depend on other data, you wouldn't really gain much.
You could do something like this:
class Singleton
{
private:
static std::unique_ptr<Singleton>& getObject()
{
static std::unique_ptr<Singleton> instance;
return instance;
}
Singleton(int foo);
public:
static void Init(int foo)
{
auto& instance = getObject();
if (instance) throw std::runtime_error("aleady inited");
instance.reset(new Singleton(foo));
}
static Singleton& getInstance()
{
auto& instance = getObject();
if (!instance) throw std::runtime_error("not inited");
return *instance;
}
};
Note that this isn't thread safe and will have undefined behaviour if multiple threads call Init or a thread calls getInstance whilst another is calling Init.
If your parameters could be replaced by template arguments then you could do it this way instead:
template <int foo>
class SingletonImpl
{
private:
SingletonImpl(int f);
public:
static SingletonImpl<foo>& getInstance()
{
static SingletonImpl<foo> instance(foo);
return instance;
}
};
using Singleton = SingletonImpl<10>;
The best solution is probably to separate initialisation and construction:
class Singleton
{
private:
std::atomic<bool> initialised;
Singleton()
: initialised(false)
{
}
Singleton& instanceImpl()
{
static Singleton singleton;
return singleton;
}
public:
void Init(int foo)
{
auto& instance = instanceImpl();
if (instance.initialised) throw std::runtime_error("already inited");
instance.initialised = true;
}
Singleton& getInstance()
{
auto& instance = instanceImpl();
if (!instance.initialised) throw std::runtime_error("not inited");
return instance;
}
};
Related
I am learning singleton design pattern and came across this piece of code
class Singleton
{
private:
static Singleton * pinstance_;
static std::mutex mutex_;
protected:
static Singleton *GetInstance(const std::string& value);
};
Singleton* Singleton::pinstance_{nullptr}; //can this line be removed?
std::mutex Singleton::mutex_; //can this line be removed?
Singleton *Singleton::GetInstance(const std::string& value)
{
std::lock_guard<std::mutex> lock(mutex_);
if (pinstance_ == nullptr)
{
pinstance_ = new Singleton(value);
}
return pinstance_;
}
since pinstance_ and mutex_ are all members of Singleton class, they are accessible by GetInstance method. So my question is: can these two definition lines be removed?
No, they can't be removed but they can be moved to local static variables of the method.
class Singleton
{
protected:
static Singleton *GetInstance(const std::string& value);
};
Singleton *Singleton::GetInstance(const std::string& value)
{
static Singleton* pinstance_{nullptr};
static std::mutex mutex_;
std::lock_guard<std::mutex> lock(mutex_);
if (pinstance_ == nullptr)
{
pinstance_ = new Singleton(value);
}
return pinstance_;
}
Also note, no guards required for initializing static variables. The compiler does it for you. Is local static variable initialization thread-safe in C++11? [duplicate]
Singleton *Singleton::GetInstance(const std::string& value)
{
static Singleton* pinstance_ = new Singleton(value);
return pinstance_;
}
Given the singleton class
class MySingleton
{
// ...
public:
MySingleTon& instance() { /* ... */ }
};
is it possible to prevent:
int main()
{
// the following should cause some error
MySingleton& singleton = MySingleton::instance();
}
while still allowing:
int main()
{
// Only directly accessing MySingleton::instance().SomeMethod should be possible
MySingleton::instance().some_method();
}
Extra example
int main()
{
// Following two lines should error
MySingleton& singleton = MySingleton::instance();
singleton.some_method();
// Following line should NOT error
// Additionally it should be the only way to access any MySingleton method besides MySingleton::instance
MySingleton::instance().some_method();
}
The only way I know to do what you are looking for is to make instance() itself be private so code that is outside of MySingleton can't call it directly, then add a static method to MySingleton that is public and uses instance() internally as needed, eg:
class MySingleton
{
// ...
private:
MySingleton() { /* ... */ }
static MySingleton& instance() { static MySingleton inst; return inst; }
public:
static void do_method() { instance().some_method(); }
};
int main()
{
MySingleton& singleton = MySingleton::instance(); // <-- ERROR
singleton.some_method();
MySingleton::do_method(); // <-- OK
}
I'm new to programing and I was trying for the program which makes the class singleton..Is this the correct approach for making a class singleton??
#include <iostream>
using namespace std;
class Singleton
{
private:
static bool instanceFlag;
static Singleton *single;
public:
static Singleton* getInstance();
void method();
~Singleton()
{
instanceFlag = false;
}
};
bool Singleton::instanceFlag = false;
Singleton* Singleton::single = NULL;
Singleton* Singleton::getInstance()
{
if(! instanceFlag)
{
single = new Singleton();
instanceFlag = true;
return single;
}
else
{
return single;
}
}
void Singleton::method()
{
cout << "Method of the singleton class";
}
int main()
{
Singleton *sc1,*sc2;
sc1 = Singleton::getInstance();
sc1->method();
sc2=Singleton::getInstance();
sc2->method();
return 0;
}
Is this the correct way of making class singleton??
You are over-complicating things. Try the Scott Meyers singleton:
struct SingletonClass {
// instance() function return a reference
static SingletonClass& instance() {
// static local variable are initialized one time.
static SingletonClass inst;
// We return the instance, which is the same for every calls.
return inst;
}
private:
// Private since we don't want other class to create instances
SingletonClass() = default;
// Our class is not copiable or movable
SingletonClass(const SingletonClass&) = delete;
SingletonClass(SingletonClass&&) = delete;
SingletonClass& operator=(const SingletonClass&) = delete;
SingletonClass& operator=(SingletonClass&&) = delete;
};
You can use your class like that:
auto& myInstance = SingletonClass::instance();
Bonus: It doesn't use dynamic allocation, it's thread safe, and is much simpler.
try this solution:
class Singleton {
private:
static Singleton* instance;
Singleton() {} // must be private
public:
static Singleton* getInstance() {
if (instance == NULL)
instance = new Singleton();
return instance;
}
void method() { cout << "Method of the singleton class\n"; }
};
Singleton* Singleton::instance = NULL;
I see errors like
src/singleton.cxx:16:error: invalid use of member 'Singleton::instance' in static member function
src/singleton.cxx:28:error: from this location
src/singleton.cxx:16:error: invalid use of member 'Singleton::instance' in static member function
src/singleton.cxx:29:error: from this location
src/singleton.cxx:16:error: invalid use of member 'Singleton::instance' in static member function
src/singleton.cxx:31:error: from this location
src/singleton.cxx: In function 'int main()':
Now after making changes I get the following errors
singleton-rhel6.3.o: In function Singleton::get_instance()':
src/singleton.cxx:27: undefined reference toSingleton::instance'
#include <cstddef>
class Singleton {
private:
Singleton();
static Singleton * instance;
int m_num;
int incr_call();
public :
static Singleton * get_instance();
};
Singleton * Singleton::get_instance() {
if(instance == NULL)
instance = new Singleton();
return instance;
}
Singleton::Singleton():
m_num(0)
{
}
int Singleton::incr_call() {
return m_num++;
}
int main() {
Singleton * s = Singleton::get_instance();
return 0;
}
instance should be static since you want to be able to call it in get_instance. Also, instance should be private:
class Singleton {
public :
static Singleton * get_instance();
private:
Singleton();
static Singleton * instance;
int m_num;
int incr_call();
};
Singleton* Singleton::instance;
You should change your constructor too, to not initialize instance:
Singleton::Singleton():
m_num(0)
{ }
Because instance is static default initialization is done and it will be NULL / nullptr.
If you have to use singleton, use Meyers' one:
class Singleton {
private:
Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public :
static Singleton& get_instance()
{
static Singleton instance;
return instance;
}
// Extra stuff
};
I have recently started working on a very old project and from the beginning of the project design pattern was not properly used. Now in one situation I want to make an already existing class a singleton class. In most tutorials I have seen that singleton classes uses a method to return object reference, like getInstance() in the following. Problem is everywhere in the project object is declared without help of any method except constructor. Is there any way to modify existing class so that without changing object creation method i can implement singleton pattern?
class Singleton
{
private:
static bool instanceFlag;
static Singleton *single;
Singleton()
{
//private constructor
}
public:
static Singleton* getInstance();
void method();
~Singleton()
{
instanceFlag = false;
}
};
bool Singleton::instanceFlag = false;
Singleton* Singleton::single = NULL;
Singleton* Singleton::getInstance()
{
if(! instanceFlag)
{
single = new Singleton();
instanceFlag = true;
return single;
}
else
{
return single;
}
}
void Singleton::method()
{
cout << "Method of the singleton class" << endl;
}
int main()
{
Singleton *sc1,*sc2;
sc1 = Singleton::getInstance();
sc1->method();
sc2 = Singleton::getInstance();
sc2->method();
return 0;
}
You can use the Pimpl idiom to do that, but remember, singletron are a bad design patterns, once you are dealing, in fact, with global variables.
Below is a simple program showing how you can do that. Note that I'm to dealing with single life time, just showing the concept:
#include <iostream>
using namespace std;
class SingletonImpl
{
public:
void method() {
cout << "Method of the singleton class" << endl;
}
};
class Singleton
{
private:
static bool instanceFlag;
static SingletonImpl *single;
public:
Singleton()
{
if ( !instanceFlag ) {
single = new SingletonImpl();
instanceFlag = true;
}
}
void method();
~Singleton()
{
// Do your life time management here
}
};
bool Singleton::instanceFlag = false;
SingletonImpl* Singleton::single = NULL;
void Singleton::method()
{
single->method();
}
int main()
{
Singleton *sc1,*sc2;
sc1 = new Singleton();
sc1->method();
sc2 = new Singleton();
sc2->method();
return 0;
}