Реляционные операторы Scoped Enums (enum class) - PullRequest
2 голосов
/ 19 мая 2019

Я посмотрел повсюду и не могу поверить, что этот вопрос еще не задавался.

Определяется ли порядок перечислителей в рамках стандарта?Скажите, если у меня есть следующее

#include <iostream>

enum class Fruits {Apple, Orange, Tomato};

int main(){

   std::cout << (Fruits::Apple < Fruits::Orange);
   std::cout << (Fruits::Orange > Fruits::Tomato);
   return 0;
}


// output:
// 1 0

Это выводит 1 0 в г ++.Но этот стандарт или специфический для компилятора?

Ответы [ 2 ]

2 голосов
/ 19 мая 2019

Чтобы завершить картину и подтвердить, что да, заказ определен. Начнем с того, почему в реляционное выражение можно поместить два перечислителя ...

[expr.rel]

2 Обычные арифметические преобразования выполняются над операндами арифметический или перечислимый тип ...

5 Если оба операнда (после преобразования) являются арифметическими или тип перечисления, каждый из операторов должен давать значение true, если указанное отношение истинно и ложно, если оно ложно.

... где обычное арифметическое преобразование для перечисления с ограниченным пространством является неоперативным ...

[выражение]

9 Многие бинарные операторы, которые ожидают операнды арифметики или Тип перечисления вызывает преобразования и приводит к типам результата в аналогичном путь. Цель состоит в том, чтобы получить общий тип, который также является типом результат. Эта модель называется обычными арифметическими преобразованиями, которые определены следующим образом:

  • Если любой из операндов имеет тип перечисления с областью действия ([dcl.enum]), преобразования не выполняются; если другой операнд не имеет такой же типа, выражение плохо сформировано.

Таким образом, они не конвертируют и могут сравниваться только с объектом того же точного типа. Значения, передаваемые перечислителям (как указано в другом ответе), определяют, если «каждый из операторов должен давать истину, если указанное отношение истинно, и ложь, если оно ложно» . Так проводится сравнение.

Стоит также отметить, что переменные типа перечисления могут принимать значения, которые не перечислены! Так, например ...

enum class foo {
  min, max = 10
};

foo mid = static_cast<foo>(5);

... является действительным, и сравнение mid > foo::min будет выполняться точно так же, поскольку предыдущий абзац обобщен и включает в себя больше, чем просто именованные значения.

2 голосов
/ 19 мая 2019

Порядок значений указан в [dcl.enum] точка 2 :

Если первый перечислитель не имеет инициализатора, значение соответствующей константы равно нулю,Определение перечислителя без инициализатора дает перечислителю значение, полученное путем увеличения значения предыдущего перечислителя на единицу.

Следовательно, значения Fruits равны 0, 1, 2 соответственно и после сравнений по перечислениямэто немного больше, чем целочисленные операции типа safe, они ведут себя так, как вы видите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...