I have this code which is an adaptation from How to pass arguments to factory elements constructors? to work with smart pointers.
#include <unordered_map>
#include <string>
#include <iostream>
#include <memory>
class Base;
class myFactory
{
public:
typedef std::unordered_map<std::string, void*> registry_map;
virtual ~myFactory() = default;
static registry_map & registry()
{
static registry_map impl;
return impl;
}
template<typename ...T>
static std::shared_ptr<Base> instantiate(std::string const & name, T&&...args)
{
auto it = registry().find(name);
if ( it == registry().end()) return 0;
typedef std::shared_ptr<Base> (*create_type)(T...);
auto create_fun = reinterpret_cast<create_type>(it->second);
return create_fun(args...);
}
template<typename F>
static bool sign(const std::string& name, F func)
{
registry()[name] = reinterpret_cast<void*>(func);
return true;
}
};
class Base: public myFactory
{
public:
virtual void f() = 0;
virtual ~Base() = default;
};
class DerivedExample : public Base
{
private:
static bool sign;
public:
DerivedExample(int a, int b){std::cout << a << b << std::endl;}
DerivedExample() = default;
static std::shared_ptr<Base> create() { return std::make_shared<DerivedExample>();}
static std::shared_ptr<Base> create(int a, int b) { return std::make_shared<DerivedExample>(a,b);}
virtual void f() override { std::cout << "DerivedExample" << std::endl; }
};
bool DerivedExample::sign = DerivedExample::myFactory::sign("DerivedExample", DerivedExample::create());
bool DerivedExample::sign = DerivedExample::myFactory::sign("DerivedExample", DerivedExample::create(int a, int b)); // redefinition
int main()
{
std::shared_ptr<Base> p1 = Base::instantiate("DerivedExample");
std::shared_ptr<Base> p2 = Base::instantiate("DerivedExample", 1, 2);
p1->f();
p2->f();
}
This implementation does not let me register 2 constructors for the factory because of a redefinition of signboolean. Is there a way to fix the code in order to register multiple create functions for the the same class?
Best regards
The bool
signis used for "auto" registration at global scope. You might just add extra variable:The way to register was wrong BTW, especially when overloads are involved.
Demo