Перечисление, основанное на целочисленном логическом преобразовании - PullRequest
4 голосов
/ 07 июля 2010

В моем проекте компилятора у меня есть перечисление, которое выглядит как

enum Result {
  No,
  Maybe,
  Yes
};

Я явно поставил No на первую позицию, чтобы я мог положиться на логическое вычисление до false. Если мой компилятор не уверен в чем-то и должен ждать фактов до времени выполнения, его функции анализа вернут Maybe. Используется как

if(!typesEqual(t1, t2)) {
  diagnose(types_unequal) << t1 << t2;
}

Интересно, считает ли вы или ваша компания плохим стилем, чтобы не сравнивать с No явно

if(typesEqual(t1, t2) == No) { /* ... */ }

Сравнение явно кажется мне многословным, но, полагаясь на неявное логическое преобразование, я чувствую себя виноватой. Было ли у вас такое чувство раньше, и как вы справились с этим?

Ответы [ 4 ]

5 голосов
/ 07 июля 2010

Я бы тоже чувствовал вину за это, потому что после прочтения кода выше что бы вы ожидали, что логическое выражение typesEqual() вернётся для Maybe?Вернется ли это правда?Может быть!Вернется ли ложь?Может быть!Мы не знаем - в этом весь смысл перечисления.Вот почему имеет смысл явно сравнивать с No, хотя это более многословно.

3 голосов
/ 07 июля 2010

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

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

Использование базового числового значения перечислителя кажется плохой идеей.

1 голос
/ 07 июля 2010

Это похоже на Boost.Tribool . Tribool поддерживает преобразования в bool для использования в условных выражениях, что, по-видимому, предполагает, что неявное преобразование в bool в таком случае неплохо, по крайней мере, в соответствии с организацией Boost (которую я считаю достаточно разумной). 1003 *

0 голосов
/ 07 июля 2010

Что мне не нравится, так это то, что он асимметричный.

Например, вы действительно хотели где-то получить

if(typesEqual(t1, t2) == Yes) {
    do_something();
}

, но случайно вы написали

if(typesEqual(t1, t2)) {
    do_something();
}

Кажется как-то странно / уродливо, что вы можете использовать логический трюк для Нет, но не для Да.

Я думаю, что решил бы это, переименовав функцию в tryCompareTypes(t1, t2), и изменив ваше перечисление на

enum Result {
  Maybe,
  No,
  Yes
};

Таким образом, tryCompareTypes() возвращает 0, если ему «не удалось» окончательно решить, равны ли типы, в противном случае он возвращает либо «Нет», либо «Да», оба из которых не равны нулю и, следовательно, указывают «успех».

...