Last active
June 3, 2016 21:12
-
-
Save eyalroz/832836d8c005ec58db76ce7c7b745fdc to your computer and use it in GitHub Desktop.
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
/** | |
* Implementation of the factory pattern, based on suggestions here: | |
* | |
* http://stackoverflow.com/q/5120768/1593077 | |
* | |
* and on the suggestions for corrections here: | |
* | |
* http://stackoverflow.com/a/34948111/1593077 | |
* | |
*/ | |
#pragma once | |
#ifndef UTIL_FACTORY_H_ | |
#define UTIL_FACTORY_H_ | |
#include <unordered_map> | |
#include <exception> | |
namespace util { | |
#ifndef UTIL_EXCEPTION_H_ | |
using std::logic_error; | |
#endif | |
template<typename Key, typename T, typename... ConstructionArgs> | |
class Factory { | |
public: | |
using Instantiator = T* (*)(ConstructionArgs...); | |
protected: | |
template<typename U> | |
static T* createInstance(ConstructionArgs... args) | |
{ | |
return new U(std::forward<ConstructionArgs>(args)...); | |
} | |
using Instantiators = std::unordered_map<Key,Instantiator>; | |
Instantiators subclassInstantiators; | |
public: | |
template<typename U> | |
void registerClass(const Key& key) | |
{ | |
// TODO: - Consider repeat-registration behavior. | |
static_assert(std::is_base_of<T, U>::value, | |
"This factory cannot register a class which is is not actually " | |
"derived from the factory's associated class"); | |
auto it = subclassInstantiators.find(key); | |
if (it != subclassInstantiators.end()) { | |
throw logic_error("Repeat registration of the same subclass in this factory."); | |
} | |
subclassInstantiators.emplace(key, &createInstance<U>); | |
} | |
public: | |
// TODO: Consider throwing on failure to find the instantiator | |
T* produce(const Key& subclass_key, ConstructionArgs... args) const | |
{ | |
auto it = subclassInstantiators.find(subclass_key); | |
if (it == subclassInstantiators.end()) { | |
return nullptr; | |
} | |
auto instantiator = it->second; | |
return instantiator(std::forward<ConstructionArgs>(args)...); | |
} | |
bool canProduce(const Key& subclass_key) const { | |
return subclassInstantiators.find(subclass_key) != subclassInstantiators.end(); | |
} | |
}; | |
} // namespace util | |
#endif /* UTIL_FACTORY_H_ */ |
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.h" | |
#include <string> | |
struct Foo | |
{ | |
Foo(int x) { }; | |
}; | |
int main() | |
{ | |
util::Factory<std::string, Foo, int> factory; | |
factory.registerClass<Foo>("foo"); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment