#cpp #enum #cpp14
Доброго времени суток. Ситуация следующая, с сервера приходит пакет, в определённом поле которого есть байт, который я хочу передавать в метод как член определённого enum’а. Для приведения я использую статик каст, но я задумался о том, что будет, если сервер пришлёт мне некорректные данные и значение в этом байте окажется за пределами enum’а. Накидал тестовый код и как оказалось С++ спокойно это проглотит и не чего не бросит (. enum class MyEnum { Red = 1, Black = 2, White = 3 }; void Foo(MyEnum val) { std::cout << static_cast(val) << std::endl; }; int main() { Foo(MyEnum::Red); Foo(static_cast (3)); Foo(static_cast (5)); system("PAUSE"); return 0; } Есть ли какие-то стандартные средства эффективно (с точки зрения производительности) проверить вхождение значения в конкретный enum и дать мне возможность бросит исключение. Если их нет, то как это сделать, не перелопачивая весь enum руками. И можно ли как то сделать foreach обход enuma не городя огород (что то типа for (auto i : MyEnum) ...)? p.s. С++ 14 компилятор GCC 6.3.
Ответы
Ответ 1
Я тут для вас кое что сооброзил, не знаю насколько поможет. Вам придется просто после добавления в перечислении, добавлять и в оператор ++ #include#include using namespace std; enum class Some { min, s1 = 3, s2 = 5, s3 = 7, max = 9, end = 100 }; Some& operator++(Some& s) { switch(s) { case Some::min: return s = Some::s1; case Some::s1: return s = Some::s2; case Some::s2: return s = Some::s3; case Some::s3: return s = Some::max; case Some::max: s = Some::end; } return s; } int main() { int n = 5, index; Some t = Some::min; while (int(t) != n && t != Some::end) { ++t; ++index; } if (t == Some::end) cout << "indefined" ; else cout << index; // выдаст 2 return 0; } Ну можно это все проделать в какой то функции, или на основе этого создавать класс - итератор. Тут index будет иметь значение как индекс в векторах... Ответ 2
#includeenum class MyEnum { Unknown = 0, Red = 1, Black = 2, White = 3, // новые значения вписывать сюда Max }; void Foo(MyEnum val) { std::cout << static_cast (val) << std::endl; } bool checkEnum(MyEnum _val) { return _val > MyEnum::Unknown && _val < MyEnum::Max; } int main() { std::cout << checkEnum(MyEnum::Red) << std::endl; std::cout << checkEnum(static_cast (3)) << std::endl; std::cout << checkEnum(static_cast (5)) << std::endl; return 0; } Вывод будет: true true false Правда тут одно ограничение, Red, Black, White - должны быть значениями по порядку, нельзя писать: enum class MyEnum { Unknown = 0, Red = 1, Black = 3, White = 6, // новые значения вписывать сюда Max }; Если же значения не идут по порядку, то возможен такой вариант, правда тут после добавления значения в enum, нужно добавить значение и в set #include #include #include enum class MyEnum { Red = 1, Black = 3, White = 6, }; static std::set enumArr{ MyEnum::Red, MyEnum::Black, MyEnum::White }; bool checkEnum(MyEnum _val) { return enumArr.find(_val) != enumArr.end(); } int main() { std::cout << std::boolalpha << checkEnum(MyEnum::Red) << " " << checkEnum(static_cast (3)) << " " << checkEnum(static_cast (5)); return 0; } Ответ 3
Enum-типы в С++ гарантируют представимость любых целочисленных значений в диапазоне от 0 до 2^n, где n - минимальное количество битов необходимое для представления явно объявленных членов enum. (Строгая формулировка более сложна, но идея именно такая.) Нет ничего нелегального в записи в enum-объекты значений из этого диапазона при помощи явного приведения типа, даже если записываемое значение не совпадает ни с одним из поименованных. Средств перечисления элементов enum в языке нет. Да и не может их быть, ибо никто не гарантировал однозначного соответствия элементов enum целочисленным значениям. Можно хоть всем им назначить одно и то же значение enum class MyEnum { Red = 1, Black = 1, White = 1 }; Ничего нелегального в этом нет. Другими словами enum-тип покрывает целый диапазон целочисленных значений, и лишь некоторые из значений этого диапазона поименованы (возможно многократно). Проверить значение на поименованность можно только вручную, т.е. в простейшем случае прямым сравнением с именованными значениями.
Комментариев нет:
Отправить комментарий