#include <iostream>
#include <type_traits>
#include <utility>
#include <memory>
using namespace std;

class Base
{
public:
	enum
	{
		BaseClass,
		Derived1Class,
		Derived2Class
	};
	
	Base() {}
	~Base() {}
	
	void printInfo() {std::cout << m_classType << std::endl;}
	
	template<typename T, typename ... Args>
	static typename std::enable_if<std::is_base_of<Base, T>::value, std::unique_ptr<T>>::type create(Args ... args)
	{
		std::unique_ptr<T> result(new T(args...));
		result->initializeImpl();
		return result;
	}
	
protected:
	int m_classType;
	
	virtual void initialize()
	{
		m_classType = BaseClass;
	}
	
private:
	void initializeImpl()
	{
		initialize();
	}
};

class Derived1 : public Base
{
public:
	Derived1()
	{
		;
	}
	
private:
	void initialize() {m_classType = Derived1Class;}
};

class Derived2 : public Base
{
public:
	Derived2()
	{
		;
	}
	
private:
	void initialize() {m_classType = Derived2Class;}
};

class Derived3 : public Base
{
public:
	Derived3(int a) : m_type(a)
	{
		;
	}
	
private:
	int m_type;

	void initialize() {m_classType = m_type;}
};

class Derived4
{
public:
	Derived4(int a) : m_type(a)
	{
		;
	}
	
private:
	int m_type;

	void initialize() {;}
};

int main() {
	auto c1 = Base::create<Derived1>();
	auto c2 = Base::create<Derived2>();
	auto c3 = Base::create<Derived3>(10);
	// auto c4 = Base::create<Derived4>(20);
	
	c1->printInfo();
	c2->printInfo();
	c3->printInfo();
	
	return 0;
}