Sorry, I finally had time. You can try the following:
#include <iostream> #include <utility> #include <functional> using namespace std; template<typename T> // Singleton policy class class Singleton { protected: Singleton() = default; Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; virtual ~Singleton() = default; public: template<typename... Args> static T& getInstance(Args... args) // Singleton { cout << "getInstance called" << std::endl; //we pack our arguments in a T&() function... //the bind is there to avoid some gcc bug static auto onceFunction = std::bind( createInstanceInternal<Args...>, args... ); //and we apply it once... return apply( onceFunction ); } private: //This method has one instance per T //so the static reference should be initialized only once //so the function passed in is called only the first time static T& apply( const std::function<T&()>& function ) { static T& instanceRef = function(); return instanceRef; } //Internal creation function. We have to make sure it is called only once... template<typename... Args> static T& createInstanceInternal(Args... args) { static T instance{ std::forward<Args>(args)... }; return instance; } };
IdeOne Link:
http://ideone.com/Wh9cX9
Edit (thread safety issues and design issues):
As far as I know, this should be thread safe in C ++ 11. Both instances and instanceRef are static local variables and should only be thread safe initialized once. Depending on your compiler, it may be, however, that the safe initialization of a C ++ 11 stream is not implemented, as specified in the standard. You can explicitly apply synchronously as a temporary workaround if that is the case. In my opinion, it is still worried that client code might call getInstance with no parameters and with parameters. If the client code calls parameters, than, most likely, it has a wait / need for a singleton to be initialized with the given parameters. Providing multiple initialization capabilities will result in unexpected / unnatural behavior for client code. It may not be good. It should be nice if Foo has only one parameter. However, this would mean that you still have to pass some arguments to get the instance ... In the end, parameterizing a singleton getInstance will cause more problems than it solves. It was said that I simply could not solve the intellectual challenge ... :-).
source share