I'm trying to implement singleton template which could instantiate (from template argument) object of the class by ctor with some set of the parameters.
The code below looks ordinary and working.
template <typename T>
class Singleton
{
public:
template<typename... Ts>
static T &instance(Ts &&...args)
{
static T instance{std::forward<Ts>(args)...};
return instance;
}
protected:
Singleton() = default;
~Singleton() = default;
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
};
there is an interesting question:
if we are trying to get the instance using different ctors, intuitively expected that is a single instance:
// create with T with some specific parameters
Singleton<MyClass>::instance(1, nullptr, "test").dosomething();
// ....
// use such version for simpler notation
// or where the paramters are not available
Singleton<MyClass>::instance().dosomething();
In C++ template terms, obviously the instances are a different due of different instantiations of template instance() function.
if we write "old style" singleton (Meyer's version) based on member pointer to the instance, it solves the problem as the instance will be outside of template class method.
So the question is - is there some technique to keep "reference-style" singleton and keep this outside of "instance()" function to prevent different instances ? or anything else?
You can store the instance in a static member. The advantage of the meyers singleton is that initialization of the instance is thread safe just by how a local static varible works. Though the same can be achieved differently. As also the static requires the implementation to use some sort of synchronization mechanism, I do not expect too much difference in terms of performance when an explicit synchronization mechanism is used. I use std::once here.
#include <memory>
#include <mutex>
#include <iostream>
template <typename T> class Singleton {
public:
template<typename... Ts> static T& instance(Ts &&...args) {
std::call_once(once,[&](){
_instance = std::make_unique<T>(std::forward<Ts>(args)...);
});
return *_instance;
}
protected:
static std::unique_ptr<T> _instance;
static std::once_flag once;
Singleton() = default;
~Singleton() = default;
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
};
template <typename T> std::unique_ptr<T> Singleton<T>::_instance;
template <typename T> std::once_flag Singleton<T>::once;
struct T {
int value;
T(int x) : value(x) { std::cout << "hello world" << std::endl; }
T() = default;
};
int main() {
std::cout << Singleton<T>::instance(42).value;
std::cout << Singleton<T>::instance().value;
}
Live Demo (note the -pthread, without it will segfault).
std::call_once ensures that only one thread enters the function and only reach the return when _instance is initialized. Effectively it is the same as the static local.
The caveat is that Singleton<T>::instance() only compiles when T has a default constructor, otherwise it not (https://godbolt.org/z/TMdGe16re). I felt that this is beyond the question being asked here and did not include a solution. You can optionally add a instance() overload that does not call the constuctor but throws an exception when _instance is not yet initialized for the case when T cannot be default constructed.
Last and least the usual dislaimer against the singleton pattern: Don't, blablablbla blablabla blablablubb, globals are evil, blablablubb.
Related
When using the Meyers singleton:
class Singleton
{
public:
static Singleton& instance()
{
static Singleton instance;
return instance;
}
void Hello()
{
std::cout <<"Hello!\n";
}
protected:
Singleton() = default;
~Singleton() {};
private:
Singleton(Singleton const&);
Singleton& operator=( Singleton const& );
};
You are able to call the instance as follow:
Singleton::instance().Hello();
or
Singleton& s = Singleton::instance();
s.Hello();
But I'm wondering if there is a way to block this:
Singleton::instance().instance();
How to avoid to call instance() as a method (with the .) and only support the static call with the :: ?
Is there a way to use static_assert, template enable_if or anything else?
First, I don't think this is a practical concern. Nobody is going to write Singleton::instance().instance().instance().Hello(). Or rather, if people are writing that on purpose, I think you have bigger problems. This is fine, as-is.
If you really want to prevent that, then you just have to move instance() outside of the class so it ceases to be a member function. There's nothing for you to assert or constrain, since you cannot tell if your static member function was called on an object or not (and you cannot overload a static member function with a non-static one taking the same argument list). Either you can write both Singleton::instance() and Singleton::instance().instance(), or neither.
Simplest is just:
class Singleton {
// ...
friend Singleton& make_singleton();
};
Singleton& make_singleton() {
static Singleton instance;
return instance;
}
Now it's just make_singleton().Hello(), and there's no other way to write that at all. This can be arbitrarily generalized by wrapping it in a singleton class template factory:
template <typename T>
struct SingletonFactory
static T& instance() {
static T instance;
return instance;
}
};
SingletonFactory<Singleton>::instance().Hello(); // ok
SingletonFactory<Singleton>::instance().instance().Hello(); // error
Under these condition i wrote the next Singleton class :
1 - i want one and only one instance of the class to be present and to be accessible from the whole game engine .
2 - the Singleton is intensively used ( thousands times per frame) so i dont want to write an extra GetInstance() function , im trying to avoid any extra function call for performance
3 - one possibility is to let the GetInstance() be inlined like this :
inline Singleton* Singleton::GetInstance()
{
static Singleton * singleton = new Singleton();
return singleton;
}
but that will cause a reference problem , on each call there will be a new reference to the singleton , to fix that wrote in c++ :
class Singleton{
private:
static Singleton* singleton;
Singleton(){}
public:
static inline Singleton* GetInstance() // now can be inlined !
{
return singleton;
}
static void Init()
{
// ofc i have to check first if this function
// is active only once
if(singleton != nullptr)
{
delete singleton;
}
singleton = new Singleton();
}
~Singleton(){} // not virtual because this class can't be inherited
};
Singleton* Singleton::singleton = nullptr;
What are the possible problems i can face with this implementation ?
Your first implementation problem is a leak of the only new you call.
And the signature that force user to check pointer validity.
Your second implementation has even more problem as you require to use a 2-step initialization, and don't forbid copy/move/assignment.
Simply use Meyers' singleton:
class Singleton{
private:
Singleton() = default;
~Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton operator&(const Singleton&) = delete;
public:
static Singleton& GetInstance()
{
static Singleton instance;
return instance;
}
};
In addition to #Jarod42's answer, I would like to point out that you could also implement a generic singleton by making template and use it in a CRTP class:
template<typename T>
class Singleton {
protected:
Singleton() = default;
~Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton operator&(const Singleton&) = delete;
public:
static T& instance() {
static T instance;
return instance;
}
};
Then extend it:
struct MySingleton : Singleton<MySingleton> { /* ... */ };
Instead of a singleton, consider a namespace! Here's how I would do it:
// thing.h
namespace thing {
// public interface
int doSomething();
}
// thing.cpp
namespace thing {
namespace {
// private data and functions can go right here :-)
int private_data_ = 1234;
int doSomethingInternal() {
return private_data_ * 2;
}
}
// public interface
int doSomething() {
return doSomethingInternal();
}
}
Usage is simple like this:
int x = thing::doSomething();
No need for getInstance(), no memory leaks, and you can't accidentally make multiple instances.
but that will cause a reference problem , on each call there will be a new reference to the singleton
Incorrect; instead there will be a new class instance which is not the same as a reference. You will most likely end up leaking memory.
static Singleton* singleton;
Use a unique_ptr instead of a raw pointer. Compiler optimizations will devolve it into a raw pointer anyway, but now you're clearly telling the compiler what its lifespan should be.
class Singleton{
private :
static Singleton* singleton;
The default scope of a class is private; you don't need to explicity say private scope.
Singleton(){}
There is no need to provide an empty constructor when you have no other constructors in the class.
im trying to avoid any extra function call for performance
Compiled C++ will often inline such code anyway.
inline Singleton* GetInstance() // now can be inlined !
Make it static...?
~Singleton(){} // not virtual because this class can't be inherited
If your intent is to make it not inheritable, then add a final keyword to the class declaration. You can then remove the destructor.
I've got a Singleton implementation where I am not sure which drawbacks it contains. Could anybody tell me how good this implementation is?
template <class Child>
class Singleton {
public:
inline static Child& Instance() {
return Instance_;
}
Singleton(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton& operator=(Singleton&&) = delete;
protected:
Singleton() = default;
private:
static Child Instance_;
};
template <typename Child> Child Singleton<Child>::Instance_;
I know of a Singleton implementation by Scott Meyers that defines the static Instance_ inside the GetInstance() function.
inline static Child& Instance() {
static Child Instance_;
return Instance_;
}
But isn't there additional overhead involved, because it has to check every time the function is invoked whether Instance_ has already been initialized.
Your solution is prone to static initialization order fiasco.
A static class member is initialized together with all global static variables; before main(), in an unspecified order. If initialization of one static variable happens to reference another one, you get undefined behavior.
Using a static variable in function, however, gives you the special guarantee: the object will only be created when the function is executed for the first time. This means that you don't have to worry about initialization order (unless you create a cycle, obviously).
Regarding performance, the checking is implemented by compiler, so it's probably tuned extremely well. As always, if you're in doubt - benchmark.
In my program I'm using one of the most common Singleton pattern used in C++ that I enhanced logically with the arrival of C++11, here is my final code :
template <class T>
class Singleton {
public:
~Singleton() = default;
static T& getInstance() {
if (instance.get() == nullptr)
instance = std::shared_ptr<T>(new T());
return *instance;
}
static void killInstance() {
instance = std::shared_ptr<T>(nullptr);
}
protected:
Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
static std::shared_ptr<T> instance;
};
template <typename T>
std::shared_ptr<T> Singleton<T>::instance(nullptr);
So all over the internet we can see this pattern taught on many sites, but I have one issue with it, in every single sites I found, it is said that every singleton must be declared this way :
class MySingleton : public Singleton<MySingleton> {
friend classSingleton<MySingleton>
};
But as far as I remember, the standard (and not only since C++11) clearly states that a class is automatically the friend of all of its children (on the contrary children are not since they it's based on parent's accessibility and inheritance's accessibility), which quite honestly makes sense. So this friend statement I see everywhere really look quite useless AND senseless isn't it? Anyone can confirm I can get rid of it without any issue?
Thanks in advance everyone ;)
But as far as I remember, the standard (and not only since C++11)
clearly states that a class is automatically the friend of all of its
children
This is a misconception. The concepts are orthogonal: a class is not a friend of its children.
I realize how many times this have been talked about but I have not found an appropriate solution for my problem. I have just implemented a Meyer's singleton class into my project but I would like to make a template out of it so that I can use it as e.g.
class Game : public Singleton<Game>
{ /* stuff */
}
And I have my class defined like this
template <typename T>
class Singleton
{
public:
static T& Instance();
private:
Singleton();
//declare them to prevent copies
Singleton(Singleton const&);
void operator=(Singleton const&);
};// END OF CLASS DEFINITION
// METHODS' DEFINITIONS
template<typename T>
T& Singleton<T>::Instance()
{
static T _instance;
return _instance;
}
Allowing ctor to be public will destroy whole vision of Singletons.
EDIT
Ok, so I have updated my Game class to befriend Singleton<Game>
class Game : public Singleton<Game>
{
friend class Singleton<Game>;
//...
}
But now I have something like:
undefined reference to 'Singleton< Game >::Singleton()'
in function Game::Game() which is empty
Allowing ctor to be public will destroy whole vision of Singletons.
No, not really. Game should have a private constructor. Constructor of Singleton is irrelevant. An instance of Singleton<Game> will not help anyone to get another instance of Game, which is what you're interested in.
Anyway, you can declare the constructor protected. Alternatively, you can keep the constructor private and befriend the template parameter. Except this does not work in C++03. Should work in C++11 though. But there's a little trick:
template <typename T>
struct wrapper
{
typedef T type;
};
template <typename T>
class Singleton
{
friend class wrapper<T>::type;
Update: Game should befriend Singleton<Game>, or at least Singleton<Game>::Instance, to allow its constructor to be called.
ctor Singleton() -> protected?