Skip to content

Instantly share code, notes, and snippets.

@mrzv
Last active November 5, 2019 21:02
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 mrzv/3738e36695b7521f86c1624ab54a4423 to your computer and use it in GitHub Desktop.
Save mrzv/3738e36695b7521f86c1624ab54a4423 to your computer and use it in GitHub Desktop.
factory-example
#include <iostream>
#include "types.hpp"
void show_registered_types()
{
std::cout << "Registered types:" << std::endl;
for (auto& x : Base::data())
std::cout << " " << x.first << std::endl;
}
int main()
{
show_registered_types();
Derived x;
show_registered_types();
Derived::registerT();
show_registered_types();
return 0;
}
#ifndef DIY_FACTORY_HPP
#define DIY_FACTORY_HPP
// From http://www.nirfriedman.com/2018/04/29/unforgettable-factory/
// with minor changes.
#include <memory>
#include <string>
#include <unordered_map>
namespace diy
{
template <class Base, class... Args>
class Factory
{
public:
template <class... T>
static Base* make(const std::string &s, T&&... args)
{
return data().at(s)(std::forward<T>(args)...);
}
virtual std::string id() const { return typeid(Base).name(); }
template <class T>
struct Registrar: Base
{
friend T;
static bool registerT()
{
const auto name = typeid(T).name();
Factory::data()[name] = [](Args... args) -> Base*
{
return new T(std::forward<Args>(args)...);
};
return true;
}
static volatile bool registered;
std::string id() const override { return typeid(T).name(); }
private:
Registrar(): Base(Key{}) { (void)registered; }
};
friend Base;
//private:
public:
class Key
{
Key(){};
template <class T> friend struct Registrar;
};
using FuncType = Base* (*)(Args...);
Factory() = default;
static std::unordered_map<std::string, FuncType>& data()
{
static std::unordered_map<std::string, FuncType> s;
return s;
}
};
template <class Base, class... Args>
template <class T>
volatile bool Factory<Base, Args...>::Registrar<T>::registered = Factory<Base, Args...>::Registrar<T>::registerT();
}
#endif
example: example.cpp
${CXX} $< -o $@ -std=c++11
#include "factory.hpp"
struct Base: public diy::Factory<Base>
{
Base(Key) {} // for Factory
};
struct Derived: public Base::Registrar<Derived> {};
namespace detail
{
inline void instantiate_derived()
{
// Instantiate Derived type to register it
Derived x;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment