#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:
	
	//single instance 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;
	}
	
	template<typename... Args>
    static T& createInstanceInternal(Args... args)
    {
		static T instance{ std::forward<Args>(args)... };
		return instance;
    }
    
};


class Foo: public Singleton<Foo>
{
    friend class Singleton<Foo>;
    Foo()
    {
        cout << "Constructing instance " << this <<" of Foo" << endl;
    }
    Foo(int x)
    {
        cout << "Constructing instance " << this <<" of Foo with argument x = "\
             << x << endl;
    }
    
    ~Foo()
    {
        cout << "Destructing instance " << this << " of Foo" << endl;   
    } 
};

int main()
{
	// this should just return the instance
    // instead, it constructs another instance
    // because invokes an overloaded version of get_instance()  
    Foo& rfoo1 = Foo::getInstance(1); 
    
    Foo& rfoo = Foo::getInstance(); // default constructible

    // this is OK
    // calls the SAME overloaded version again, instance is static
    // so we get the same instance
    Foo& rfoo2 = Foo::getInstance(2); 
}