#include <unordered_map>
#include <typeindex>
template <class Base>
class clone_factory
{
public:
using function_type = Base*(*)(Base&); // smart pointer/ggf. std::function und so sollten noch ergaenzt werden!
template <class Derived>
void register_type(function_type func)
{
map_[typeid(Derived)] = func;
}
Base* clone(Base &b) const
{
return map_.at(typeid(b))(b);
}
private:
std::unordered_map<std::type_index, function_type> map_;
};
template <class Base, class Derived, typename FuncT>
void register_types(clone_factory<Base> &clone, FuncT &&head)
{
clone.template register_type<Derived>(std::forward<FuncT>(head));
}
template <class Base, class Derived, class ... Deriveds, typename FuncT, typename ... FuncTs>
void register_types(clone_factory<Base> &clone,
FuncT &&head, FuncTs&&... functions) // Syntax geht bestimmt auch schoener.
{
clone.template register_type<Derived>(std::forward<FuncT>(head));
register_types<Base, Deriveds...>(clone, std::forward<FuncTs>(functions)...);
}
#include <iostream>
class base {public: virtual ~base() {}};
class derived1 : public base {};
class derived2 : public base {};
base* get_derived1(base &)
{
std::cout << "derived1\n";
return nullptr;
}
base* get_derived2(base &)
{
std::cout << "derived2\n";
return nullptr;
}
int main() try
{
clone_factory<base> factory;
register_types<base, derived1, derived2>(factory, get_derived1, get_derived2);
derived1 d1;
derived2 d2;
factory.clone(d1);
factory.clone(d2);
}
catch(std::exception &ex)
{
std::cerr << "Error: " << ex.what() << '\n';
}
I2luY2x1ZGUgPHVub3JkZXJlZF9tYXA+CiNpbmNsdWRlIDx0eXBlaW5kZXg+Cgp0ZW1wbGF0ZSA8Y2xhc3MgQmFzZT4KY2xhc3MgY2xvbmVfZmFjdG9yeQp7CnB1YmxpYzoKCXVzaW5nIGZ1bmN0aW9uX3R5cGUgPSBCYXNlKigqKShCYXNlJik7IC8vIHNtYXJ0IHBvaW50ZXIvZ2dmLiBzdGQ6OmZ1bmN0aW9uIHVuZCBzbyBzb2xsdGVuIG5vY2ggZXJnYWVuenQgd2VyZGVuIQoKCXRlbXBsYXRlIDxjbGFzcyBEZXJpdmVkPgoJdm9pZCByZWdpc3Rlcl90eXBlKGZ1bmN0aW9uX3R5cGUgZnVuYykKCXsKCQltYXBfW3R5cGVpZChEZXJpdmVkKV0gPSBmdW5jOwoJfQoKCUJhc2UqIGNsb25lKEJhc2UgJmIpIGNvbnN0Cgl7CgkJcmV0dXJuIG1hcF8uYXQodHlwZWlkKGIpKShiKTsKCX0KCnByaXZhdGU6CglzdGQ6OnVub3JkZXJlZF9tYXA8c3RkOjp0eXBlX2luZGV4LCBmdW5jdGlvbl90eXBlPiBtYXBfOwp9OwoKdGVtcGxhdGUgPGNsYXNzIEJhc2UsIGNsYXNzIERlcml2ZWQsIHR5cGVuYW1lIEZ1bmNUPgp2b2lkIHJlZ2lzdGVyX3R5cGVzKGNsb25lX2ZhY3Rvcnk8QmFzZT4gJmNsb25lLCBGdW5jVCAmJmhlYWQpCnsKCWNsb25lLnRlbXBsYXRlIHJlZ2lzdGVyX3R5cGU8RGVyaXZlZD4oc3RkOjpmb3J3YXJkPEZ1bmNUPihoZWFkKSk7Cn0KCgp0ZW1wbGF0ZSA8Y2xhc3MgQmFzZSwgY2xhc3MgRGVyaXZlZCwgY2xhc3MgLi4uIERlcml2ZWRzLCB0eXBlbmFtZSBGdW5jVCwgdHlwZW5hbWUgLi4uIEZ1bmNUcz4Kdm9pZCByZWdpc3Rlcl90eXBlcyhjbG9uZV9mYWN0b3J5PEJhc2U+ICZjbG9uZSwKCQkJCQlGdW5jVCAmJmhlYWQsIEZ1bmNUcyYmLi4uIGZ1bmN0aW9ucykgLy8gU3ludGF4IGdlaHQgYmVzdGltbXQgYXVjaCBzY2hvZW5lci4KewoJY2xvbmUudGVtcGxhdGUgcmVnaXN0ZXJfdHlwZTxEZXJpdmVkPihzdGQ6OmZvcndhcmQ8RnVuY1Q+KGhlYWQpKTsKCXJlZ2lzdGVyX3R5cGVzPEJhc2UsIERlcml2ZWRzLi4uPihjbG9uZSwgc3RkOjpmb3J3YXJkPEZ1bmNUcz4oZnVuY3Rpb25zKS4uLik7Cn0KCiNpbmNsdWRlIDxpb3N0cmVhbT4KCmNsYXNzIGJhc2Uge3B1YmxpYzogdmlydHVhbCB+YmFzZSgpIHt9fTsKY2xhc3MgZGVyaXZlZDEgOiBwdWJsaWMgYmFzZSB7fTsKY2xhc3MgZGVyaXZlZDIgOiBwdWJsaWMgYmFzZSB7fTsKCmJhc2UqIGdldF9kZXJpdmVkMShiYXNlICYpCnsKCXN0ZDo6Y291dCA8PCAiZGVyaXZlZDFcbiI7CglyZXR1cm4gbnVsbHB0cjsKfQoKYmFzZSogZ2V0X2Rlcml2ZWQyKGJhc2UgJikKewoJc3RkOjpjb3V0IDw8ICJkZXJpdmVkMlxuIjsKCXJldHVybiBudWxscHRyOwp9CgppbnQgbWFpbigpIHRyeQp7CgljbG9uZV9mYWN0b3J5PGJhc2U+IGZhY3Rvcnk7CglyZWdpc3Rlcl90eXBlczxiYXNlLCBkZXJpdmVkMSwgZGVyaXZlZDI+KGZhY3RvcnksIGdldF9kZXJpdmVkMSwgZ2V0X2Rlcml2ZWQyKTsKCWRlcml2ZWQxIGQxOwoJZGVyaXZlZDIgZDI7CglmYWN0b3J5LmNsb25lKGQxKTsKCWZhY3RvcnkuY2xvbmUoZDIpOwp9CmNhdGNoKHN0ZDo6ZXhjZXB0aW9uICZleCkKewoJc3RkOjpjZXJyIDw8ICJFcnJvcjogIiA8PCBleC53aGF0KCkgPDwgJ1xuJzsKfQo=