#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;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDx1dGlsaXR5PgojaW5jbHVkZSA8bWVtb3J5Pgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKY2xhc3MgQmFzZQp7CnB1YmxpYzoKCWVudW0KCXsKCQlCYXNlQ2xhc3MsCgkJRGVyaXZlZDFDbGFzcywKCQlEZXJpdmVkMkNsYXNzCgl9OwoJCglCYXNlKCkge30KCX5CYXNlKCkge30KCQoJdm9pZCBwcmludEluZm8oKSB7c3RkOjpjb3V0IDw8IG1fY2xhc3NUeXBlIDw8IHN0ZDo6ZW5kbDt9CgkKCXRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIC4uLiBBcmdzPgoJc3RhdGljIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPHN0ZDo6aXNfYmFzZV9vZjxCYXNlLCBUPjo6dmFsdWUsIHN0ZDo6dW5pcXVlX3B0cjxUPj46OnR5cGUgY3JlYXRlKEFyZ3MgLi4uIGFyZ3MpCgl7CgkJc3RkOjp1bmlxdWVfcHRyPFQ+IHJlc3VsdChuZXcgVChhcmdzLi4uKSk7CgkJcmVzdWx0LT5pbml0aWFsaXplSW1wbCgpOwoJCXJldHVybiByZXN1bHQ7Cgl9CgkKcHJvdGVjdGVkOgoJaW50IG1fY2xhc3NUeXBlOwoJCgl2aXJ0dWFsIHZvaWQgaW5pdGlhbGl6ZSgpCgl7CgkJbV9jbGFzc1R5cGUgPSBCYXNlQ2xhc3M7Cgl9CgkKcHJpdmF0ZToKCXZvaWQgaW5pdGlhbGl6ZUltcGwoKQoJewoJCWluaXRpYWxpemUoKTsKCX0KfTsKCmNsYXNzIERlcml2ZWQxIDogcHVibGljIEJhc2UKewpwdWJsaWM6CglEZXJpdmVkMSgpCgl7CgkJOwoJfQoJCnByaXZhdGU6Cgl2b2lkIGluaXRpYWxpemUoKSB7bV9jbGFzc1R5cGUgPSBEZXJpdmVkMUNsYXNzO30KfTsKCmNsYXNzIERlcml2ZWQyIDogcHVibGljIEJhc2UKewpwdWJsaWM6CglEZXJpdmVkMigpCgl7CgkJOwoJfQoJCnByaXZhdGU6Cgl2b2lkIGluaXRpYWxpemUoKSB7bV9jbGFzc1R5cGUgPSBEZXJpdmVkMkNsYXNzO30KfTsKCmNsYXNzIERlcml2ZWQzIDogcHVibGljIEJhc2UKewpwdWJsaWM6CglEZXJpdmVkMyhpbnQgYSkgOiBtX3R5cGUoYSkKCXsKCQk7Cgl9CgkKcHJpdmF0ZToKCWludCBtX3R5cGU7CgoJdm9pZCBpbml0aWFsaXplKCkge21fY2xhc3NUeXBlID0gbV90eXBlO30KfTsKCmNsYXNzIERlcml2ZWQ0CnsKcHVibGljOgoJRGVyaXZlZDQoaW50IGEpIDogbV90eXBlKGEpCgl7CgkJOwoJfQoJCnByaXZhdGU6CglpbnQgbV90eXBlOwoKCXZvaWQgaW5pdGlhbGl6ZSgpIHs7fQp9OwoKaW50IG1haW4oKSB7CglhdXRvIGMxID0gQmFzZTo6Y3JlYXRlPERlcml2ZWQxPigpOwoJYXV0byBjMiA9IEJhc2U6OmNyZWF0ZTxEZXJpdmVkMj4oKTsKCWF1dG8gYzMgPSBCYXNlOjpjcmVhdGU8RGVyaXZlZDM+KDEwKTsKCS8vIGF1dG8gYzQgPSBCYXNlOjpjcmVhdGU8RGVyaXZlZDQ+KDIwKTsKCQoJYzEtPnByaW50SW5mbygpOwoJYzItPnByaW50SW5mbygpOwoJYzMtPnByaW50SW5mbygpOwoJCglyZXR1cm4gMDsKfQ==