Skip to content

Instantly share code, notes, and snippets.

@jdiego
Created September 26, 2019 02:39
Show Gist options
  • Save jdiego/8719fd0332df4fc257e9dea1f8edaf2a to your computer and use it in GitHub Desktop.
Save jdiego/8719fd0332df4fc257e9dea1f8edaf2a to your computer and use it in GitHub Desktop.
#include <memory>
#include <unordered_map>
#include <typeindex>
#include <iostream>
std::unordered_map<std::type_index, std::shared_ptr<void>(*)(void const*)> cloners;
template <typename Derived>
struct cloneable
{
std::shared_ptr<Derived> clone() const {
return std::static_pointer_cast<Derived>(cloners[typeid(*this)](this));
}
protected:
cloneable() {
static int const init_dummy = []{
cloners[typeid(Derived)] = [](void const* original) -> std::shared_ptr<void> {
return std::make_shared<Derived>(*static_cast<Derived const*>(original));
};
return 0;
}();
}
virtual ~cloneable() = default;
};
struct B : cloneable<B> {};
struct C : cloneable<C>, B {};
struct D : cloneable<D>, B {};
int main()
{
std::shared_ptr<B> b1 = std::make_shared<D>();
std::shared_ptr<B> b2 = b1->clone();
std::cout << typeid(*b2).name(); // D
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment