Безошибочное преобразование строки в перечисляемый класс
У меня есть такой класс enum (я планирую добавить в него больше опций позже):
enum class ViSequencePointType {
JumpToValue = 0,
RampToValue = 1
};
Затем у меня есть текстовый файл конфигурации, который каждая строка должна представлять одно из значений перечисления. Что-то вроде этого:
1
0
255
A
WTF
Мне нужно проанализировать этот файл и создать вектор этого enum-класса... поэтому я делаю что-то вроде:
bool conversionResult = false;
int colThree = line.toInt(&conversionResult);
if(!conversionResult) {
//failed to convert to integer
} else {
ViSequencePointType pt = static_cast<ViSequencePointType>(colThree);
switch(pt) {
case ViSequencePointType::JumpToValue:
break;
case ViSequencePointType::RampToValue:
break;
default:
break;
}
для этого default
в случае, если компилятор говорит
Метка по умолчанию в switch, которая охватывает все значения перечисления
что я считаю, что это означает, что если в текстовом файле существует недопустимая запись, я не могу это выяснить!
Итак, как я могу решить эту проблему, не допуская недопустимого перечисления во время выполнения?
0 ответов
Для того, чтобы охватить недействительные / бессмысленные значения перечисления, обычной практикой является
- полагаться на то, что последующим значениям перечисления неявно присваивается значение предыдущего значения перечисления + 1
- добавить
"Invalid"
значение enum с самым низким значением в enum (неявно 0, или вы можете присвоить ему низкое значение, такое как-1
) - добавить
"Max"
значение enum при наибольшем значении в enum
Вот пример:
enum class ViSequencePointType
{
Invalid = -1,
JumpToValue, // is implicitly assigned enum value 0 (-1 + 1 == 0)
RampToValue, // is implicitly 1 (JumpToValue + 1)
CrawlToValue, // etc...
HopToValue,
// add new values here
Max // Max must be the last value in the enum
};
Теперь, когда вы анализируете входное значение, вы можете проверить, что интегральное значение больше Invalid
и меньше чем Max
и если да, то вы знаете, что это допустимое значение перечисления
ViSequencePointType parse(const std::string& value)
{
bool converted = false;
int val = line.toInt(&converted);
if(!converted)
{
// do additional conversion failure handling here if necessary
return ViSequencePointType::Invalid;
}
if (val <= static_cast<int>(ViSequencePointType::Invalid) ||
val >= static_cast<int>(ViSequencePointType::Max)
{
// do additional out of bounds handling here if necessary
return ViSequencePointType::Invalid;
}
return static_cast<ViSequencePointType>(val);
}
Теперь вы знаете выход parse
является допустимым значением перечисления, с выводом для неизвестных / недействительных значений, обозначенных значением перечисления Invalid
,