#include <memory>
template<typename> class FactoryImpl;
template<> class FactoryImpl<void> {
struct secret { };
friend class Base;
};
template<typename T>
class FactoryImpl : T {
public:
template<typename... Args>
static std::unique_ptr<class Base> create (Args&&... args) {
return std::unique_ptr<class Base> (new FactoryImpl (std::forward<Args> (args) ...));
}
private:
template<typename... Args>
FactoryImpl (Args&&... args)
: T (std::forward<Args> (args) ... )
{ }
virtual void _not_allowed (FactoryImpl<void>::secret) { };
};
class Base {
public:
virtual ~Base () { }
private:
virtual void _not_allowed (FactoryImpl<void>::secret) = 0;
};
template<typename T, typename... Args>
std::unique_ptr<Base> factory (Args&&... args) {
return FactoryImpl<T>::create (std::forward<Args> (args) ...);
}
struct Derived : Base {
Derived () { }
Derived (int i) { }
};
int
main (int argc, char *argv[])
{
factory<Derived> ();
factory<Derived> (123);
// Derived d; // <- ERROR
}
I2luY2x1ZGUgPG1lbW9yeT4KCnRlbXBsYXRlPHR5cGVuYW1lPiBjbGFzcyBGYWN0b3J5SW1wbDsKCnRlbXBsYXRlPD4gY2xhc3MgRmFjdG9yeUltcGw8dm9pZD4gewogIHN0cnVjdCBzZWNyZXQgeyB9OwogIGZyaWVuZCBjbGFzcyBCYXNlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVD4KY2xhc3MgRmFjdG9yeUltcGwgOiBUIHsKICBwdWJsaWM6CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBBcmdzPgogICAgc3RhdGljIHN0ZDo6dW5pcXVlX3B0cjxjbGFzcyBCYXNlPiBjcmVhdGUgKEFyZ3MmJi4uLiBhcmdzKSB7CiAgICAgIHJldHVybiBzdGQ6OnVuaXF1ZV9wdHI8Y2xhc3MgQmFzZT4gKG5ldyBGYWN0b3J5SW1wbCAoc3RkOjpmb3J3YXJkPEFyZ3M+IChhcmdzKSAuLi4pKTsKICAgIH0KCiAgcHJpdmF0ZToKICAgIHRlbXBsYXRlPHR5cGVuYW1lLi4uIEFyZ3M+CiAgICBGYWN0b3J5SW1wbCAoQXJncyYmLi4uIGFyZ3MpCiAgICAgIDogVCAoc3RkOjpmb3J3YXJkPEFyZ3M+IChhcmdzKSAuLi4gKQogICAgeyB9CgogICAgdmlydHVhbCB2b2lkIF9ub3RfYWxsb3dlZCAoRmFjdG9yeUltcGw8dm9pZD46OnNlY3JldCkgeyB9Owp9OwoKY2xhc3MgQmFzZSB7CiAgcHVibGljOgogICAgdmlydHVhbCB+QmFzZSAoKSB7IH0KCiAgcHJpdmF0ZToKICAgIHZpcnR1YWwgdm9pZCBfbm90X2FsbG93ZWQgKEZhY3RvcnlJbXBsPHZvaWQ+OjpzZWNyZXQpID0gMDsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lLi4uIEFyZ3M+CnN0ZDo6dW5pcXVlX3B0cjxCYXNlPiBmYWN0b3J5IChBcmdzJiYuLi4gYXJncykgewogIHJldHVybiBGYWN0b3J5SW1wbDxUPjo6Y3JlYXRlIChzdGQ6OmZvcndhcmQ8QXJncz4gKGFyZ3MpIC4uLik7Cn0KCgpzdHJ1Y3QgRGVyaXZlZCA6IEJhc2UgewogIERlcml2ZWQgKCkgICAgICB7IH0KICBEZXJpdmVkIChpbnQgaSkgeyB9Cn07CgoKaW50Cm1haW4gKGludCBhcmdjLCBjaGFyICphcmd2W10pCnsKICBmYWN0b3J5PERlcml2ZWQ+ICgpOwogIGZhY3Rvcnk8RGVyaXZlZD4gKDEyMyk7CgogIC8vIERlcml2ZWQgZDsgLy8gPC0gRVJST1IKfQo=