Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Недостатки стандартного enum'а, Оцените альтернативу 
:(
    Опции темы
SaDFromSpb
Дата 8.10.2008, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 5.4.2006
Где: Санкт-Петербург

Репутация: 3
Всего: 3



Всегда раздражали стандартные enum'ы как минимум двумя вещами :
Первая вещь:
Код

enum MyEnum {ONE, TWO, THREE};

// ONE, TWO, THREE попадают в область видимости, такую же как у MyEnum, а не скрываются внутри (как это сделано в яве). Имеем проблему: при создании какого-нибудь енума с элементами вроде LEFT, RIGHT, DOWN, UP в очень общем хедере рискуем, что такие имена могут быть нечаянно перекрыты в пользовательском коде. Есть два Выхода:
1) Добавление префиксов
Код

enum Directions {
   DIRS_LEFT,
   DIRS_RIGHT,
   ...
};
, что утомляет.

2) Сокрыте в нэймспейсе
Код

namespace Directions {
 enum DirectionsT {
   LEFT,
   RIGHT,
  ...
 };
}
, что делает использование не очень удобным, заставляя оперировать двумя именами Directions и DirectionsT. Конечно же нэймспейс может быть более общим,  включающим тот код, который использует этот enum, но не всегда хочется его создавать.

Вторая вещь:
Код

//usage:
MyEnum me = static_cast<MyEnum>(20); // will compile successfully

Иногда хочется не допустить, чтоб кто-нибудь мог присвоить енуму значение не из первоначального списка инициализации.




Предлагается следующее решение:

Код


// Making enum-class with name NAME with standart enum-like behaviour
#define MAKE_ENUM(NAME, ...)                    \
  class NAME {                            \
  public:                                            \
  enum EnumT {__VA_ARGS__};                                    \
  NAME(EnumT v)        : m_value(v) {}                \
  explicit NAME(int v) : m_value(static_cast<EnumT>(v)) {}    \
  operator EnumT ()      { return m_value; }            \
  private:                                    \
  EnumT  m_value;                                \
  };


// As above, but do not allow assignation to arbitrary integers values
#define MAKE_ENUM_STRICT(NAME, ...)                    \
  class NAME {                                \
  public:                                \
  enum EnumT {__VA_ARGS__};                        \
  NAME(EnumT v)        : m_value(v) {}                    \
  operator EnumT ()      { return m_value; }                \
  private:                                \
  EnumT  m_value;                            \
  };




И его использование:

Код


MAKE_ENUM(MyEnum, 
      GOOD, 
      OR, 
      GOBLIN);


MAKE_ENUM_STRICT(MyEnumStrict, 
         SOME, 
         BIG, 
         BONE);



int main() {


  MyEnum  me = MyEnum::OR;
  //  me = 4;  // not allowed like for standart enums.
  me = static_cast<MyEnum>(4);  // allowed like for standart enums.
  
  MyEnumStrict mes = MyEnumStrict::BIG;

  
  //   mes = static_cast<MyEnumStrict>(4);  // not allowed, but you can still do this dirty trick:
  mes = static_cast<MyEnumStrict::EnumT>(4); // I can't find out, how to hide inner EnumT type for this case.
  //  May be, I should call it not "EnumT" but "__Ugly_Inner_Enum_Type_Name_Not_For_Use_Outside__" =))

  //   mes = (MyEnumStrict)4; // Old-style type cast not allowed also.

  me = static_cast<MyEnum>(mes);   // allowed
  // mes = static_cast<MyEnumStrict>(me); // not allowed.
  

  // Enum with predefines still supported:
  MAKE_ENUM(OtherEnum, SIX=6, SEVEN, EIGHT);

  OtherEnum oe = OtherEnum::SEVEN;

  cout << oe << endl; // will print 7

  return 0;
}




Правда вот, не знаю, поддерживается ли __VA_ARGS__ всеми компиляторами. Нужно будет глянуть в стандарте...

Замечания и критика приветствуются.



--------------------
"За исключением части, касающейся потоков, библиотека Loki написана на стандартном языке С++. Увы, это означает, что многие современные компиляторы не смогут работать с ней в полном объеме." (А. Александреску. Modern C++ design. 2001)
PM   Вверх
mrbrooks
Дата 8.10.2008, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 2
Всего: 306



пардон за  smile   smile 
бедный enum. досталось ему.
PM MAIL   Вверх
mes
Дата 8.10.2008, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SaDFromSpb @  8.10.2008,  16:09 Найти цитируемый пост)
Сокрыте в нэймспейсе
namespace Directions {
 enum DirectionsT {
   LEFT,
   RIGHT,
  ...
 };
}
, что делает использование не очень удобным, заставляя оперировать двумя именами Directions и DirectionsT. Конечно же нэймспейс может быть более общим,  включающим тот код, который использует этот enum, но не всегда хочется его создавать.

 а если написать так, то что неудобно?
Код

namespace Directions {
 enum Enum/*или Kind или другое не конфликтующее по смыслу с неймспейсом название*/ 
{
   LEFT,
   RIGHT,
  ...
 };
}


Добавлено через 6 минут и 14 секунд
Цитата(SaDFromSpb @  8.10.2008,  16:09 Найти цитируемый пост)
 MyEnumStrict mes = MyEnumStrict::BIG;
  //   mes =

 smile не пойму и чего это мне название переменной такое знакомое ?!  smile 



--------------------
PM MAIL WWW   Вверх
Alek86
Дата 8.10.2008, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



до принятия нового стандарта не так уж и много осталось - там энамы уже нормальные


--------------------
user posted image    user posted image
PM MAIL   Вверх
SaDFromSpb
Дата 8.10.2008, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 5.4.2006
Где: Санкт-Петербург

Репутация: 3
Всего: 3



Цитата(mes @  8.10.2008,  16:34 Найти цитируемый пост)
 а если написать так, то что неудобно?

Получается
Directions::Enum dir = Directions::LEFT;
Неудобно.

Цитата(Alek86 @  8.10.2008,  16:53 Найти цитируемый пост)
до принятия нового стандарта не так уж и много осталось - там энамы уже нормальные 

Круто! Всё лень его изучить. Значит, не одному мне старые енумы не нравились.....  smile

Добавлено через 6 минут и 3 секунды
Хотя, я думаю, еще во многих консервативных конторах, вроде моей, будут долго отторгать новый стнадарт, мотивируя это требованием, чтоб создаваемый код на старых клиентских платформах собирался....

Это сообщение отредактировал(а) SaDFromSpb - 8.10.2008, 17:16


--------------------
"За исключением части, касающейся потоков, библиотека Loki написана на стандартном языке С++. Увы, это означает, что многие современные компиляторы не смогут работать с ней в полном объеме." (А. Александреску. Modern C++ design. 2001)
PM   Вверх
mes
Дата 8.10.2008, 17:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SaDFromSpb @  8.10.2008,  17:12 Найти цитируемый пост)
О том, что ты написал - там вообще нету типа для енума.

это как  нету ?

Цитата(mes @  8.10.2008,  16:34 Найти цитируемый пост)
namespace Directions {
 enum Enum


Цитата(SaDFromSpb @  8.10.2008,  17:12 Найти цитируемый пост)
Directions::EnumT dir = Directions::LEFT;

A зачем T на конце  ? весь вид портит ..

Добавлено через 3 минуты и 18 секунд
Цитата(SaDFromSpb @  8.10.2008,  16:09 Найти цитируемый пост)
Иногда хочется не допустить, чтоб кто-нибудь мог присвоить енуму значение не из первоначального списка инициализации.

а с этим согласен. )


--------------------
PM MAIL WWW   Вверх
SaDFromSpb
Дата 8.10.2008, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 5.4.2006
Где: Санкт-Петербург

Репутация: 3
Всего: 3



Цитата(mes @  8.10.2008,  17:24 Найти цитируемый пост)
это как  нету ?

Это я не заметил. Я свое предыдущее сообщение отредактировал.


--------------------
"За исключением части, касающейся потоков, библиотека Loki написана на стандартном языке С++. Увы, это означает, что многие современные компиляторы не смогут работать с ней в полном объеме." (А. Александреску. Modern C++ design. 2001)
PM   Вверх
korian
Дата 8.10.2008, 20:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



не зняю
не вижу вариантов, когда енум должен сущствовать сам по себе (если это C++)
т.е. любой енум есть составляющая какого-то класса
да, может быть такое что в классе несколько енумов, но обычно их имена не пересекаються.
по поводу

Цитата(SaDFromSpb @  8.10.2008,  15:09 Найти цитируемый пост)
MyEnum me = static_cast<MyEnum>(20); 

если я захочу, я забью любое значение в любое место памяти, так что защищаться от этого нет смысла
если человек пишет MyEnum me = static_cast<MyEnum>(20)
значит он знает, что он делает (а если нет, то надо бить по рукам)


Это сообщение отредактировал(а) korian - 8.10.2008, 20:28
PM   Вверх
SaDFromSpb
Дата 8.10.2008, 21:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 5.4.2006
Где: Санкт-Петербург

Репутация: 3
Всего: 3



Цитата(korian @  8.10.2008,  20:28 Найти цитируемый пост)
не вижу вариантов, когда енум должен сущствовать сам по себе (если это C++)

Не хочу здесь об этом =). Да. В принципе, можно всегда делать енумы внутри классов... Правда, бывает, что целая группа классов равноправно разделяет какой-то енум, но это данному подходу - не преграда. =)


Цитата(korian @  8.10.2008,  20:28 Найти цитируемый пост)
если я захочу, я забью любое значение в любое место памяти, так что защищаться от этого нет смысла

А че, спецификаторами доступа в классах тоже не пользуешься, что ли?
А вообще это менее важный аспект из двух.


--------------------
"За исключением части, касающейся потоков, библиотека Loki написана на стандартном языке С++. Увы, это означает, что многие современные компиляторы не смогут работать с ней в полном объеме." (А. Александреску. Modern C++ design. 2001)
PM   Вверх
vinter
Дата 9.10.2008, 07:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата(SaDFromSpb @  8.10.2008,  22:14 Найти цитируемый пост)
А че, спецификаторами доступа в классах тоже не пользуешься, что ли?

если сильно захотеть, то можно ив private переменную записать. Сломать можно все, что хочешь. Вопрос только в смысле этих действий.


--------------------
Мой блог
PM MAIL WWW   Вверх
Alek86
Дата 9.10.2008, 09:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Цитата(korian @  8.10.2008,  20:28 Найти цитируемый пост)
т.е. любой енум есть составляющая какого-то классада, может быть такое что в классе несколько енумов, но обычно их имена не пересекаються.

а в какой класс ты запихаешь enum Color, если он используется в трети классов программы?


--------------------
user posted image    user posted image
PM MAIL   Вверх
Lycifer
Дата 9.10.2008, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 144
Регистрация: 4.11.2007

Репутация: нет
Всего: нет



C++ не удобства, а язык с возможностями
А то как писать enum -  это стиль программирования, поэтому это не недостаток!!!
В С++ есть более плохие вещи которые распространяются на ошибка в самом языке.
Пример: Все знаю что к закрытым полям класса нельзя получить доступ не из этого класса, но также при необходимости все получают!!!!

это все пиши есчё((((
PM MAIL ICQ   Вверх
korian
Дата 9.10.2008, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



Цитата(Alek86 @  9.10.2008,  08:31 Найти цитируемый пост)
а в какой класс ты запихаешь enum Color, если он используется в трети классов программы?

1. запихнуть его в неймспейс со всей этой третей частью
2. скорее всего из всей этой третей части, есть класс, которому этот колор нужен больше всего, а остальные его используют, т.к. работают с этим объектом.

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1234 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.