#c
#c
Вопрос:
#include <iostream>
#include <string>
#include <vector>
#include <map>
std::vector<std::pair<std::string, [type of the object, entity or banana]>> nep; //[type of the object, entity or banana] is my imaginary type
class Entity
{
private:
int x;
public:
Entity(const int x) : x(x) {};
int GetX() const { return x; };
};
class Banana
{
private:
int y;
public:
Banana(const int y) : y(y) {};
int GetY() const { return y; };
};
[type of the object, entity or banana] CreateObj(std::string name) //Used that imaginary variable here again
{
for (unsigned short int i = 0; i < nep.size(); i )
{
if (nep.at(i).first == name)
{
return [new object with type = nep.at(i).second];
}
}
}
int main()
{
nep.push_back({ "ent", Entity });
nep.push_back({ "banan", Banana });
CreateObj(banan).GetY();
std::cin.get();
}
[тип объекта, сущности или банана] — это моя вещь типа воображаемой переменной.
Что я хотел бы сделать, так это передать туда класс, например, а затем с помощью CreateObj()
функции я хотел бы создать новый объект этого типа и использовать его.
Как я могу это сделать?
Комментарии:
1. ИМХО, если вы пытаетесь создавать объекты на лету, статическая фабрика (шаблон проектирования фабрики) была бы уместна. Вы бы представляли свои типы как
enum class
для безопасности типов, а не как строки.2. Вы можете использовать std::variant , он предназначен для таких случаев. ( en.cppreference.com/w/cpp/utility/variant )
Ответ №1:
Короткий ответ: нет
Длинный ответ:
У вас есть такие инструменты, как std::type_index
и typeid
, но они не будут делать то, что вы хотите.
Однако вы можете сохранить заводскую функцию вместо типа:
using result = std::any; // or some other common type
std::map<std::string, std::function<std::any()>> nep;
nep["banana"] = []{ return Banana{}; };
nep["entity"] = []{ return Entity{}; };
// Call the functions:
result my_banana = nep["banana"]();
Bananaamp; b = std::any_cast<Bananaamp;>(my_banana);
Функции, хранящиеся в map, создают экземпляры известного типа. Поскольку карта должна хранить функции одного и того же типа, она должна быть возвращена через общий тип. Этот общий тип может быть std::any
, std::variant<Banana, Entity>
или указателем на базовый класс.
Затем вы можете выполнить поиск по карте для заводской функции и вызвать ее, чтобы получить созданный объект. Он должен быть правильно развернут, чтобы получить доступ к переменной через правильный тип для доступа к членам.
Ответ №2:
Если вы не хотите использовать полиморфизм, вы можете что-то сделать с помощью метапрограммирования:
enum class ClassType {
EntityType,
BananaType,
};
namespace internal {
template <ClassType Type>
struct _build_type {};
template <>
struct _build_type<ClassType::EntityType> {
constexpr auto operator()() {
return EntityType();
}
};
template <>
struct _build_type<ClassType::BananaType> {
constexpr auto operator()() {
return BananaType();
}
};
}
И затем, ваш объект конструкции:
template <ClassType Type>
constexpr auto create_instance() {
return internal::_build_type<Type>{}();
}
Итак, вы можете сделать:
const auto object = create_instance<BananaType>();
Это увеличит время компиляции, но не приведет к снижению производительности во время выполнения.