Skip to content

Instantly share code, notes, and snippets.

@potados99
Created December 14, 2023 09:49
Show Gist options
  • Save potados99/6eb45216e384cf6ce83e93c90f8fe5cb to your computer and use it in GitHub Desktop.
Save potados99/6eb45216e384cf6ce83e93c90f8fe5cb to your computer and use it in GitHub Desktop.
Self registering factory pattern, modified
/*
Original source code from: https://www.nirfriedman.com/2018/04/29/unforgettable-factory/
*/
#include <iostream>
#include <string>
#include <vector>
template<class Base>
class Factory {
public:
friend Base;
static Base *find(const std::string &s) {
for (Base *instance: Factory::data()) {
if (instance->match(s)) {
return instance;
}
}
throw 9;
}
template<class T>
struct Registrar : Base {
friend T;
static bool registered;
static bool registerT() {
Factory::data().push_back(new T());
return true;
}
private:
Registrar() : Base(Key{}) { (void) registered; }
};
private:
class Key {
Key() {};
template<class T> friend
struct Registrar;
};
static std::vector<Base *> &data() {
static std::vector<Base *> instances;
return instances;
}
};
template<class Base>
template<class T>
bool Factory<Base>::Registrar<T>::registered = Factory<Base>::Registrar<T>::registerT();
struct Animal : Factory<Animal> {
Animal(Key) {}
virtual void makeNoise() = 0;
virtual bool match(const std::string &s) = 0;
};
class Dog : public Animal::Registrar<Dog> {
public:
Dog() {}
bool match(const std::string &s) { return s.compare("Dog") == 0; }
void makeNoise() { std::cerr << "Dog: " << 123 << "\n"; }
};
class Cat : public Animal::Registrar<Cat> {
public:
Cat() {}
bool match(const std::string &s) { return s.compare("Cat") == 0; }
void makeNoise() { std::cerr << "Cat: " << 123 << "\n"; }
};
int main() {
auto x = Animal::find("Cat");
auto y = Animal::find("Dog");
std::cout << "Hello, World!" << std::endl;
x->makeNoise();
y->makeNoise();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment