Last active
November 5, 2019 21:02
-
-
Save mrzv/3738e36695b7521f86c1624ab54a4423 to your computer and use it in GitHub Desktop.
factory-example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
example: example.cpp | |
${CXX} $< -o $@ -std=c++11 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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