Вывести тип класса из строки

Как описано в Этот ответ, вы можете определить производный объект из строки, если вы знаете базовый тип. Я хотел сделать код более гибким, сделав шаблон BaseFactory шаблоном, что приведет к следующему скомпилируемому коду.

#include <iostream>
#include <string>
#include <map>///Reflect and Register
#define MyType(BASE, TYPE) \
static Registerer<BASE, TYPE> reg

#define Register(BASE, TYPE) \
Registerer<BASE, TYPE> TYPE::reg(#TYPE)

template<class B>
class Factory
{
public:
static B* from(const std::string& name)
{
return mapping[name];//should check if its a member
}
static void add(const std::string& name, B* instance)
{
mapping[name] = instance;
}
static std::map<std::string, B*> mapping;
};
template<class B>
std::map<std::string, B*> Factory<B>::mapping = std::map<std::string, B*>();template<class B, class D>
class Registerer
{
public:
Registerer(const std::string& name)
{
Factory<Base>::add(name, new D);//actually add
}
};
///Deduce and Register///Class examples implementing Registration
class Base
{
public:
Base()
{
name = "Base Class";
}
const std::string& getName()
{
return name;
}
protected:
std::string name;
};
class Derived1 : public Base
{
public:
Derived1()
{
name = "I am type 1.\n";
}
MyType(Base, Derived1);
};
Register(Base, Derived1);
class Derived2 : public Base
{
public:
Derived2()
{
name = "I am type 2.\n";
}
MyType(Base, Derived2);
};
Register(Base, Derived2);
///Class examples implementing Registrationint main()
{
std::string typeString1 = "Derived1";
std::string typeString2 = "Derived2";

std::cout << Factory<Base>::from(typeString1)->getName();
std::cout << Factory<Base>::from(typeString2)->getName();

return 0;
}

Однако этот код дает сбой, по-видимому, потому что Factory :: mapping не создается во время, когда вызовы Registerer добавляют. Как описано в Этот ответ, есть решение, которое заключается в добавлении строки

template class Factory<Base>;

которая не решает проблему в Visual Studio, что я и использую. Другая возможность состоит в том, чтобы явно создать новый класс, но в первую очередь нужно было использовать шаблон. Итак, я придумал это:

template<class B>
class Factory
{
public:
static B* from(const std::string& name, B* instance = NULL)
{
static std::map<std::string, B*> mapping;
if(instance != NULL)
{
mapping[name] = instance;
return NULL;
}
else//should check if name is in map first
return mapping[name];
}
};

Это работает, поскольку переменная отображения инициализируется при первом вызове функции. Неудачной частью является проверка if.

Я пытаюсь найти решения, которые:

  1. Не использует одну функцию в Factory для симуляции двух.

  2. Способ зарегистрировать класс одной строкой вместо двух.

  3. Возможность заставить дочерний класс Base зарегистрироваться самостоятельно, чтобы пользователь случайно не зарегистрировал его.

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]