Я довольно новичок в C / C ++, обычно я пишу на C #, поэтому у меня есть вопрос:
enum PrimitiveType {
BOOL,
STRING,
INT8,
INT16,
INT32,
UINT8,
UINT16,
UINT32,
};struct MyValue
{
public:
String Id
PrimitiveType ValueType;
[???] Value;
};
Я хочу хранить int
s, string
с и bool
в этом "Value"
имущество.
В C # я бы объявил Value
как объект и привести объект к int
или же bool
лайк:
if(myValueObject.ValueType == BOOL)
auto value = (bool)myValueObject.ValueType;
Какой тип я могу использовать здесь, в C ++?
Канонический ответ на это будет 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
Помощник с этой страницы может создавать действительно лаконичный код, который действует по-разному в зависимости от сохраненного значения.
Как уже упоминалось, std::variant
это, вероятно, лучшее решение, но вам нужен C ++ 17. Если C ++ 17 является опцией, вы также можете использовать станд :: любой.
Если вы используете версию, предшествующую C ++ 17, я рекомендую использовать союз декларация.