// Test1.cpp: определяет точку входа для консольного приложения.
//
#include <memory>
#include <utility>
#include <functional>

template <typename T> 
struct Callable;

template <typename R, typename... Args> 
struct Callable <R(Args...)>
{
	virtual R operator () (Args&&...) {}
};

template <typename T> 
class Function;

template <typename R, typename... Args> 
class Function<R(Args...)>
{
	typedef std::unique_ptr <Callable<R(Args...)>> Ptr;
	Ptr ptr;

	template <typename T>
	class Realisation : public Callable<R(Args...)>
	{
		T t;
	public :
		R operator () (Args&&... args)
		{
			return t(std::forward<Args>(args)...);
		}

		Realisation () {}

		Realisation(T&& at) : t(std::move(at)) 
		{}
	};

public :
	R operator () (Args&&... args)
	{
		return ptr->operator () (std::forward<Args>(args)...);
	}

	Function () 
	{}

	template <typename T>
	Function (T&& t): ptr(std::make_unique<Realisation<T>>(std::move(t)))
	{}
};

int main()
{	
	Function<void(const char*)> f = [] (const char* a) { printf("%s\n", a); };
	f("Hello, world!");

	getchar();
    return 0;
}

