Как бы я использовал тип в качестве «переменной»?

#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(), я хотел бы создать новый объект этого типа и использовать его. Как я могу это сделать?

ИМХО, если вы пытаетесь создавать объекты на лету, подойдет статическая фабрика (фабричный шаблон проектирования). Вы бы представляли свои типы как enum class для безопасности типов, а не как строки.

rranjik 06.04.2019 23:13

Вы можете использовать std::variant, он предназначен для таких случаев. (en.cppreference.com/w/cpp/utility/вариант)

mohabouje 06.04.2019 23:14
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Краткий ответ: нет

Длинный ответ:

У вас есть такие инструменты, как 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"]();
Banana& b = std::any_cast<Banana&>(my_banana);

Функции, хранящиеся в карте, создают экземпляры известного типа. Так как карта должна хранить функции одного типа, она должна быть возвращена через общий тип. Этот общий тип может быть std::any, std::variant<Banana, Entity> или указателем на базовый класс.

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

Если вы не хотите использовать полиморфизм, вы можете сделать что-то с метапрограммированием:

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>();

Эта штука увеличит время компиляции, но не повлияет на производительность во время выполнения.

Другие вопросы по теме