#include <iostream>
#include <memory>
#include <string>
#include <map>
struct Base
{
static std::shared_ptr<Base> Create(int params)
{
std::cout << "Creating Base with params = " << params << "\n";
return std::make_shared<Base>();
}
};
namespace Utility
{
struct FactoryToolBase
{
virtual std::shared_ptr<Base> Create(int params) = 0;
};
template<typename T> struct FactoryTool: FactoryToolBase
{
std::shared_ptr<Base> Create(int params)
{
return T::Create(params);
}
};
struct Factory
{
std::map<std::string, std::unique_ptr<FactoryToolBase>> tools;
template<typename T> Factory& Register(std::string name)
{
tools[name] = std::unique_ptr<FactoryToolBase>(new FactoryTool<T>);
return *this;
}
std::shared_ptr<Base> Create(std::string name, int params)
{
return tools[name]->Create(params);
}
};
}
namespace Trivial
{
struct Derived: Base
{
static std::shared_ptr<Base> Create(int params)
{
if (params == 0)
{
return Base::Create(params);
}
else
{
std::cout << "Creating Derived with params = " << params << std::endl;
return std::make_shared<Derived>();
}
}
};
}
namespace Complex
{
template<typename T> struct Inherited
{
static std::shared_ptr<Base> Create(int params)
{
return T::Create(params);
}
};
struct Derived: Base, Inherited<Base>
{
static std::shared_ptr<Base> Create(int params)
{
if (params == 0)
{
return Inherited::Create(params);
}
else
{
std::cout << "Creating Derived with params = " << params << std::endl;
return std::make_shared<Derived>();
}
}
};
struct EvenMoreDerived: Base, Inherited<Derived>
{
static std::shared_ptr<Base> Create(int params)
{
if (params < 1000)
{
return Inherited::Create(params);
}
else
{
std::cout << "Creating EvenMoreDerived with params = " << params << std::endl;
}
}
};
}
int main()
{
std::cout << "Trivial static inheritance" << std::endl;
Utility::Factory trivial;
trivial
.Register<Base>("Base")
.Register<Trivial::Derived>("Derived");
trivial.Create("Base", 123); // -> Base::Create(123)
trivial.Create("Derived", 0); // -> Base::Create(0)
trivial.Create("Derived", 123); // -> Derived::Create(123)
std::cout << std::endl << "Complex static inheritance" << std::endl;
Utility::Factory complex;
complex
.Register<Base>("Base")
.Register<Complex::Derived>("Derived")
.Register<Complex::EvenMoreDerived>("EvenMoreDerived");
complex.Create("Base", 123); // -> Base::Create(123)
complex.Create("Derived", 0); // -> Base::Create(0)
complex.Create("Derived", 123); // -> Derived::Create(123)
complex.Create("EvenMoreDerived", 0); // -> Base::Create(0)
complex.Create("EvenMoreDerived", 123); // -> Derived::Create(123)
complex.Create("EvenMoreDerived", 1234); // -> EvenMorederived::Create(1234)
return 0;
}