enum class в switch case конструкций можно использовать если в switch стоит переменный с underlying type of enum

Raiden LuiKang
Raiden LuiKang

Пример, который не скомплируется в с++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"  переменный может имет любой допустимый значений.

 

-4
рейтинг
5 комментариев
Nate Reinar Windwood

Контрпродуктивно: вся суть enum class в строгой типизации. Если нужен только скоупинг — засуньте enum в неймспейс.

Nate Reinar Windwood
Raiden LuiKang

Nate Reinar Windwood,  enum class  очень удобно в компайл тайм вычеслениях,  а реальный пример где можно использовать его в рантайм есть?  Я свой проекте все enum ы перевел на enum class  и об этом сожелел, пришлось для каждого  enum class написать  операция сравнений на int  .  Конца, концов отказал от этий идей.

 

Raiden LuiKang
Raiden LuiKang
// Вот один пример.

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");
}

Raiden LuiKang
Raiden LuiKang

Я не предлагаю,   изменить каких либо свойства 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 ;
}


 

Raiden LuiKang
Обновлено 
Виктор Губин

Чем вас не устраивает

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()

2. В других языках такое уже есть :)

Виктор Губин
Обновлено 
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения