Skip to content

Instantly share code, notes, and snippets.

@loganek
Last active October 30, 2016 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loganek/c0c8dfb30cd72a5a1a47b3701b61d3da to your computer and use it in GitHub Desktop.
Save loganek/c0c8dfb30cd72a5a1a47b3701b61d3da to your computer and use it in GitHub Desktop.
Automatically create collection of instances of derived classes
// Automatically create collection of instances of derived classes
// Blog post: http://www.cookandcommit.eu/2016/10/automatic-collection-of-instances-of.html
#include <memory>
#include <typeindex>
#include <unordered_map>
template <typename Derived, typename Base>
struct Registrar
{
template<typename ...Args>
Registrar(Args&&... args)
{
Base::registry()[typeid(Derived)] =
std::make_shared<Derived>(std::forward<Args>(args)...);
}
};
template<typename T>
struct Registrable
{
typedef std::unordered_map<std::type_index, std::shared_ptr<T>> collection_t;
template<typename R>
using Registrar = Registrar<R, T>;
static collection_t & registry()
{
static collection_t collection;
return collection;
}
};
#include <iostream>
class Base : public Registrable<Base>
{
public:
virtual void print_myself() = 0;
};
class WithParameter : public Base
{
int x;
public:
WithParameter(int x) : x(x) {}
void print_myself() override
{
std::cout << "WithParameter(" << x << ")" << std::endl;
}
static Registrar<WithParameter> registrar;
};
WithParameter::Registrar<WithParameter> WithParameter::registrar(25);
class NoParameter : public Base
{
public:
void print_myself() override
{
std::cout << "NoParameter" << std::endl;
}
static Registrar<NoParameter> registrar;
};
NoParameter::Registrar<NoParameter> NoParameter::registrar;
int main(int /*argc*/, char **/*argv*/)
{
for (auto x : Base::registry()) {
x.second->print_myself();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment