for для перечислений

Georgy Firsov
Georgy Firsov

Как можно сейчас:

enum class EMyEnum {
  Min,
  First = Min,
  Second,
  ...
  Last,
  Max
};

...

for (std::underlying_type_t<EMyEnum> eMyEnum = EMyEnum::Min; eMyEnum < EMyEnum::Max; eMyEnum++) {
   ...
}

Но это с новым кодом, а есть ещё и старый, который менять не всегда можно, что делает такой трюк невозможным. Собственно, предложение состоит в следующем: хотелось бы делать одним из следующих способов:

enum class EMyEnum {
   First,
   Second,
   ...
   Last
};

...

// (1)
for (auto eMyEnum : EMyEnum) { ... }

// (2)
for (auto eMyEnum = begin(EMyEnum); eMyEnum != end(EMyEnum); eMyEnum++) { ... }

Думаю, что можно и иные синтаксические кострукции придумать, но пока смысла в этом не вижу. Первый же вариант кажется более лаконичным.

Тут есть скользкий вопрос - перечисления вот таких типов:

// (1)
enum class EMyBadEnum1 {
  First = 0,
  Second = 2,
  Third = 6,
  Last = 7,
  Invalid = -2
};

// (2)
enum class EMyBadEnum2 {
  First,
  Second,
  Third = First
  Last
};

В обоих случаях можно разрешить данные неприятности проходом от минимального до максимального элемента (не обязательно по порядку их определения). Шаг же инкремента тут не обязательно будет равным единице, что обеспечить легко, так как на этапе компиляции значения перечисления известны.

Повторяющиеся значения перечисления считаются одинаковыми в данном контексте (т.е. в примере с EMyBadEnum2 будет 3 итерации цикла).

 

Для чего оно нужно:

Это поможет писать менее чувствительный к изменениям код, так как, например, при написании DLL разумно иногда кодировать различные опции в перечислении, но иногда подобный код во имя большей простоты требует написания "цикла" по перечислению, что со старым кодом (где нежелательно вводить служебные значения Min и Max) иногда превращается в набор if-else или switch, хотя можно было бы действительно обойтись циклом по данному перечислению.
И вот это та ситуация, модификация кода в которой (добавление новой опции) могла бы быть облегчена подобным циклом: достаточно добавить просто значение в перечисление, без необходимости модификации существующего кода. Это один из use-кейсов.

7
рейтинг
1 комментарий
Andrey

Решается reflection-ом (в частности, в Reflection TS -- https://cplusplus.github.io/reflection-ts/draft.pdf -- есть get_enumerators).

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