Как динамически хранить примитивные типы в одном свойстве?

Я довольно новичок в C / C ++, обычно я пишу на C #, поэтому у меня есть вопрос:

enum PrimitiveType {
BOOL,
STRING,
INT8,
INT16,
INT32,
UINT8,
UINT16,
UINT32,
};struct MyValue
{
public:
String Id
PrimitiveType ValueType;
[???] Value;
};

Я хочу хранить ints, stringс и boolв этом "Value" имущество.
В C # я бы объявил Value как объект и привести объект к int или же bool лайк:

if(myValueObject.ValueType == BOOL)
auto value = (bool)myValueObject.ValueType;

Какой тип я могу использовать здесь, в C ++?

2

Решение

Канонический ответ на это будет std::variant, Тогда я бы избавился от этого перечисления, так как оно вводит множество источников истины:

using PrimitiveValue = std::variant<bool, String, int8_t, int16_t, int32_t, uint8_t, uint16_t, uint32_t>;

struct MyValue {
String id;
PrimitiveValue val;
};

Если вам абсолютно необходимо получить значение enum, вам понадобится отображение:

PrimitiveType MyValue::getPrimitiveType() const {
if (val.holds_alternative<bool>()) { return BOOL; }
else if (val.holds_alternative<String>()) { return STRING; }
else if (val.holds_alternative<int8_t>()) { return INT8; }
// else ...
}

Это гарантирует, что никогда не может возникнуть состояние, в котором дескриптор типа не соответствует фактически сохраненному значению, потому что variant гарантирует это.

Тем не менее, ваш «C # способ» воздействия на такое значение не лучший вариант здесь. Гораздо приятнее std::visit который вместе с overloaded Помощник с этой страницы может создавать действительно лаконичный код, который действует по-разному в зависимости от сохраненного значения.

5

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

Как уже упоминалось, std::variant это, вероятно, лучшее решение, но вам нужен C ++ 17. Если C ++ 17 является опцией, вы также можете использовать станд :: любой.

Если вы используете версию, предшествующую C ++ 17, я рекомендую использовать союз декларация.

1

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