ideas
ideas copied to clipboard
enum class в switch case конструкций можно использовать если в switch стоит переменный с underlying type of enum
Перенос предложения: голоса +3, -7 Автор идеи: ??
Пример, который не скомплируется в с++11 или слудующих версий, потому что enum color не конвертируется на "int" . Но в switch case здесь никакое присваивание enum color на каких либо int не происходят.
enum class color{ red, blue, white };
int main()
{
int value = read_value_from_anywhere_other_library();
switch( value )
{
case color::red : printf("This is a red color\n"); break;
case color::bllue : printf("This is a blue color\n"); break;
case color::white : printf("This is a white color\n"); break;
default: printf("This is not a color\n");
}
return 0;
}
Предлагаю, добавить автогенерация оператор сравнение enum class с его underlying type . Чтобы легко сравнивать и использовать их в if else , switch case и других местах.
Тот пример , изменим и делаем работающий код для нынешного стандарт С++, будет UB:
enum class color{ red, blue, white };
int main()
{
int value = read_value_from_anywhere_other_library();
switch( (enum color) value ) // converting has a UB.
{
case color:: red: printf("This is a red color\n"); break;
case color:: blue: printf("This is a blue color\n"); break;
case color:: white: printf("This is a white color\n"); break;
default: printf("This is a not color\n");break;
}
}
Если не ошибаюсь, в с++17 конвертация целый число в enum class будет UB, если этот целый число значение имеет больше бит чем enum class элементы используется. В данном случий, enum class color -- элементам хватить 3 бит, а "value" переменный может имет любой допустимый значений.
Nate Reinar Windwood, 17 апреля 2019, 19:46 Контрпродуктивно: вся суть enum class в строгой типизации. Если нужен только скоупинг — засуньте enum в неймспейс.
Удалённый пользователь, 18 апреля 2019, 15:51 Nate Reinar Windwood, enum class очень удобно в компайл тайм вычеслениях, а реальный пример где можно использовать его в рантайм есть? Я свой проекте все enum ы перевел на enum class и об этом сожелел, пришлось для каждого enum class написать операция сравнений на int . Конца, концов отказал от этий идей.
Удалённый пользователь, 18 апреля 2019, 15:57
// Вот один пример.
struct table_row
{
int id;
int color;
};
enum class color{ red, blue, white } ;
void read_from_db(table_row& row)
{
row = read_from_outside_library();
// Не комплириуется без operator != ( int , enum color ) overload.
if ( row.color != color::red && row.color != color::blue && row.color != color.white )
throw std::runtime_error("row.color invalid");
}
Удалённый пользователь, 18 апреля 2019, 16:05 Я не предлагаю, изменить каких либо свойства enum class а.
Предлагаю, implicit добавить operation == , != , < , > , <= , >= с enum class and its underlying-type.
Например, если вот эту компилятор сам генерирует, будет здорово!
template< typename Enum >
bool operator == ( Enum e, typename std::underlying_type<Enum>::type value)
{
return static_cast< typename std::underlying_type<Enum>::type > ( e ) == value ;
}
template< typename Enum >
bool operator == ( typename std::underlying_type<Enum>::type value , Enum e)
{
return static_cast< typename std::underlying_type<Enum>::type > ( e ) == value ;
}
Виктор Губин, 2 августа 2019, 12:38 Чем вас не устраивает
switch( static_cast<color>(value) )
?
Внутри enum так или иначе это unsigned integer, есть только возможность "подрезать" тип. Скажем для Windows/DOS символов консоли,
enum class color: uint8_t { red = 0x04; green = 0x02; blue = 0x01 };
естественно static_cast попросту сведет байт к двойному слову.
К сожалению привять дополнительное константное значаение другого типа прямо внути enum С++ нельзя, хотя было-бы очень полезным:
enum class error_condition {
ok("no error") = 0,
file_not_found("no such file or directory") = 1
public:
constexp const char* message() const noexcept {
return msg_;
}
private:
explicit constexpr error_condition(const char* msg) noexcept:
msg_(msg)
{}
const char* msg_;
}
Тогда вообще отпадет надобность писать switch, достаточно просто спросить у константы
ec.message()
- В других языках такое уже есть :)
Чем вас не устраивает
switch( static_cast<color>(value) )
?
Это UB, если value нековертируем
template< typename Enum > bool operator == ( Enum e, typename std::underlying_type<Enum>::type value) { return static_cast< typename std::underlying_type<Enum>::type > ( e ) == value ; } template< typename Enum > bool operator == ( typename std::underlying_type<Enum>::type value , Enum e) { return static_cast< typename std::underlying_type<Enum>::type > ( e ) == value ; }
А это - почти полное стирание грани между enum class и enum classic. Если добавить еще operator=
, то будет совсем полное.
Лучше бы в стандартную библиотеку добавить такое:
enum class Enum
{
X = 1,
Y = 100,
};
std::is_enumerated<Enum>(1); // true
std::is_enumerated<Enum>(101); // false
Объявить реализацию как unspecified
и жить спокойно в ожидании нормальной рефлексии (которую хрен пойми когда привезут).