Ответ 1
Да, объявление абсолютно корректно и переносимо как в C, так и в С++.
В обоих C и С++ это:
enum State {DISABLED=0, ENABLED=!DISABLED};
в точности эквивалентно этому:
enum State {DISABLED=0, ENABLED=1};
и к этому:
enum State {DISABLED, ENABLED};
но по разным причинам.
В C унарный оператор !
дает результат типа int
со значением либо 0
(если операнд не равен 0
) или 1
(если операнд равен 0
). !x
эквивалентно x == 0
. (Любое ненулевое значение считается истинным при использовании в качестве условия, но операторы !
и ==
, среди прочих, всегда дают результат точно 0
или 1
.) Константы перечисления всегда имеют тип int
; если задано значение, оно при необходимости преобразуется в int
.
(C добавил тип _Bool
в стандарте 1999 года, но все операторы, которые дают логически "логические" значения, все еще дают результаты типа int
.)
В С++ результат унарного оператора !
имеет тип bool
. Результат: false
или true
, где оператор C !
дал бы 0
или 1
соответственно. Как и в C, если задано значение, оно преобразуется по мере необходимости; значения bool
false
и true
преобразуются в 0
и 1
соответственно.
В C константы перечисления всегда имеют тип int
. В С++ они относятся к типу перечисления, в этом случае enum State
.
Ссылаясь на более раннюю константу перечисления в одном объявлении типа, является законным. Каждая константа перечисления становится видимой после объявления.
Что-то вроде:
enum bool { false = 0, true = !false );
становится более четким, чем
enum bool { false = 0, true = 1 };
(в C, это было бы незаконно в С++), я почтительно не согласен. Константа 1
совершенно понятна любому, кто знаком с C. Переписывание его как !false
не помогает. Фактически, когда <stdbool.h>
недоступен (что-то редкое в наши дни), я использовал:
typedef enum { false, true } bool;
Тот факт, что false
и true
будут заданы их правильные значения, является IMHO достаточно очевидным.
Что касается того, почему C99 не использовал определение enum
, как это, я подозреваю, потому что каждый тип перечисления совместим с некоторым целым числом, определенным для реализации. (Для gcc обычно это unsigned int
или int
.) Комитет хотел, чтобы _Bool
был отдельным типом с рангом преобразования ниже любого другого целочисленного типа. (И они не могли сделать bool
ключевое слово без нарушения существующего кода.)