Невозможно в C ++ создать экземпляр класса по имени, определенному во время выполнения. C ++ обладает очень малой способностью отражать .
Однако вы могли бы создать поддержку для него самостоятельно. Идея в том, чтобы создать карту name-string для фабричной функции, которая возвращает экземпляр этого типа. Возвращенный экземпляр должен быть заключен в std::any
, потому что C ++ - как язык со строгой и статической типизацией - не может позволить определить тип возвращаемого значения во время выполнения.
Существует функция add_factory
, которая должна вызываться для всех типов, которые вы хотите создать, используя имя. Существует также вспомогательный макрос, который, как и все макросы, работает из-за магии.
auto& factories() {
static std::unordered_map<std::string, std::any(*)()> factories;
return factories;
}
template<class T>
void
add_factory(const char* name) {
// further development: take function as argument so that
// non-default-constructible classes can be supported
factories()[name] = []() -> std::any {
return T{};
};
}
std::any
create(const char* name)
{
const auto& f = factories();
if (f.find(name) != f.end())
return f.find(name)->second();
throw std::runtime_error("I haven't heard of this type");
}
// don't use this macro in header files
#define ADD_FACTORY(name) namespace { auto dummy_##name = (add_factory<name>(#name), 0); }
// ----- usage -----
struct a {
int i;
};
ADD_FACTORY(a)
struct b {
double d;
};
ADD_FACTORY(b)
// factories are not limited to classes
ADD_FACTORY(int)
int main()
{
std::any instance = create("a");
assert(std::any_cast<a>(&instance));
}