116 lines
3.1 KiB
C++
116 lines
3.1 KiB
C++
#ifndef INSTANTIATOR_H
|
|
#define INSTANTIATOR_H
|
|
|
|
#include <map>
|
|
#include <list>
|
|
#include <set>
|
|
#include <memory>
|
|
|
|
/**
|
|
* @brief The Instantiator_T class - base instantiator (abstract factory) template
|
|
* @param ClassId_T - unique class identification class. For example string, or integer id.
|
|
* @param BaseClass_T - all objects should have one base class. For example vehicle or parameter
|
|
* @param Args - constructor arguments
|
|
*
|
|
* Usage example:
|
|
* @code
|
|
* class Base_T {
|
|
* public:
|
|
* virtual int get() = 0;
|
|
* }
|
|
*
|
|
* class Derived1_T : public Base_T {
|
|
* public:
|
|
* Derived1_T (int start) : m_start(start){}
|
|
* int get() override {
|
|
* return m_start + 1;
|
|
* }
|
|
* private:
|
|
* int m_start = 0;
|
|
* }
|
|
*
|
|
* class Derived2_T : public Base_T {
|
|
* public:
|
|
* Derived1_T (int start) : m_start(start){}
|
|
* int get() override {
|
|
* return m_start + 2;
|
|
* }
|
|
* private:
|
|
* int m_start = 0;
|
|
* }
|
|
* .
|
|
* .
|
|
* .
|
|
* Instantiator_T <std::string, Base_T, int> instantiator;
|
|
* instantiator.registerType<Derived1>("one");
|
|
* instantiator.registerType<Derived2>("2");
|
|
*
|
|
* auto d1 = instantiator.create ("one")(10);
|
|
* auto d2 = instantiator.create ("2")(10);
|
|
*
|
|
* d1->get();
|
|
* d2->get();
|
|
* @endcode
|
|
*/
|
|
template<class ClassId_T, class BaseClass_T, class ... Args>
|
|
class Instantiator_T {
|
|
public:
|
|
/**
|
|
* @brief BaseClass_SP - base class shared pointer type
|
|
*/
|
|
typedef std::shared_ptr<BaseClass_T> BaseClass_SP;
|
|
/**
|
|
* @brief instantiatorFunction - instantiator function pointer type. Generally speaking it is pointer to constructor.
|
|
*/
|
|
typedef BaseClass_SP (*instantiatorFunction) (Args ...);
|
|
|
|
Instantiator_T() = default;
|
|
|
|
/**
|
|
* @brief registerType - template function to register class in factory
|
|
* @param Derived - registering type
|
|
* @param id - unique class identification
|
|
*
|
|
* Usage example:
|
|
* @code
|
|
* instantiator.registerType<Derived1>("one");
|
|
* instantiator.registerType<Derived2>("2");
|
|
* @endcode
|
|
*/
|
|
template<class Derived>
|
|
void registerType (ClassId_T id) {
|
|
/// store pointer to constructor of Derived class
|
|
classes[id] = &instantiator<Derived>;
|
|
}
|
|
|
|
/**
|
|
* @brief create - create class by unique id. Class should be registered before
|
|
* @param id - unique class identification
|
|
* @return shared pointer to new class.
|
|
* @throws std::our_of_range when id not found in map
|
|
*/
|
|
instantiatorFunction create (ClassId_T id) const {
|
|
/// constructor of registered type will call here
|
|
return classes.at (id);
|
|
}
|
|
protected:
|
|
/**
|
|
* @brief classes - main storage for pointers to constructors of registered types
|
|
*/
|
|
std::map<ClassId_T, instantiatorFunction> classes;
|
|
|
|
private:
|
|
/**
|
|
* @brief instantiator - main functionality, create registered object
|
|
* @param Derived - class type
|
|
* @param args - constructor arguments
|
|
* @return shared pointer to register Derived class
|
|
*/
|
|
template<class Derived>
|
|
static BaseClass_SP instantiator (Args ... args) {
|
|
return std::make_shared<Derived> (args ...);
|
|
}
|
|
};
|
|
|
|
#endif // INSTANTIATOR_H
|