Являются ли множественные условные операторы в этой ситуации хорошей идеей?

Я только что увидел этот блок кода в статье Wikipedia об условных операторах:

Vehicle new_vehicle = arg == 'B' ? bus      :
                      arg == 'A' ? airplane :
                      arg == 'T' ? train    :
                      arg == 'C' ? car      :
                      arg == 'H' ? horse    :
                      feet;

Я немного изменил код, но идея такая же. Вы нашли бы это использование условного оператора приемлемым? Это гораздо более кратким, чем конструкция if - else, и с помощью коммутатора определенно откроется целый новый набор возможностей для ошибок (проваливается кто-нибудь?). Кроме того, if - else и switch не могут использоваться как значения R, поэтому вам нужно сначала создать переменную, инициализировать ее и затем назначить по мере необходимости.

Я действительно так люблю, но мне интересно, что думают другие.

Но форматирование имеет важное значение.

EDIT: Мне все еще нравится это. Но я понимаю тех, кто говорит, что для этого было сделано выражение switch. Хорошо, может быть, так. Но что, если условия являются вызовами функций, возвращающими bool? Или миллион других вещей, которые вы не можете включить.

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

Ответ 1

Я использовал этот тип конструкции много раз. Пока он отлично отформатирован (т.е. Не все на одной строке, что делает его нечитаемым), я не вижу проблемы с ним.

Ответ 2

Я бы использовал переключатель, потому что это то, для чего он был предназначен. Да, существует риск ошибок при сбое, но этот вложенный-условный блок имеет гораздо более высокий риск того, что другие программисты будут неправильно поняты.

Ответ 3

Это отличный пример использования условного оператора. Я использую его таким образом все время в С++, Java и Perl.

Ответ 4

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

Замена с помощью if else или для построения коммутатора требует, чтобы фрагмент

"new_vehicle =  "

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

Ответ 5

Мне это нравится. Это похоже на лестницу if-else-if, только более кратким.

Ответ 6

Там много пробелов вокруг символьных констант, что делает его немного трудным для чтения. Я бы скорректировал сравнения: (и, возможно, переместите последнее значение в строке.)

Vehicle new_vehicle = (arg == 'B') ? bus      :
                      (arg == 'A') ? airplane :
                      (arg == 'T') ? train    :
                      (arg == 'C') ? car      :
                      (arg == 'H') ? horse    :
                                     feet;

Теперь он выглядит великолепно.

Ответ 7

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

Оператор переключения будет более неуклюжим. Это потребует, чтобы переменная была объявлена ​​и затем инициализирована, обычно это плохая идея, если ее можно избежать. Это потребует больше ввода текста, и у вас будет больше мест для ошибок. Это будет не так ясно, так как нужно будет посмотреть на каждый случай, чтобы увидеть, что он сказал что-то вроде new_vehicle = foo; break;.

Если вы собираетесь делать это только здесь, то наличие условной версии в порядке, это хорошо, поскольку это сразу показывает, что происходит. Если это произойдет не один раз, подумайте о том, чтобы включить его в функцию, так что есть только одно место для обновления, если что-то изменится (например, "R" для перевозки или "L" для вертолета).

Ответ 8

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

Ответ 9

Чисто стилистический выбор. Для небольших наборов данных, таких как вы здесь, тогда, пока ваша команда разработчиков не выбрасывается такой штукой, то это прекрасно в моей книге.

Ответ 10

Vehicle new_vehicle = getVehicleByType(arg);

Vehicle getVehicleByType(char arg){
  if (arg == 'B') return bus;
  if (arg == 'A') return airplane;
  if (arg == 'C') return car;
  if (arg == 'T') return train;
  if (arg == 'H') return horse;
  return feet;
}

Мне нравится это лучше. Вложенные условные умны, но я думаю, что это почти так же кратким и с меньшей вероятностью путает будущего читателя. Извините, если синтаксис выключен, в настоящее время я не делаю много C.

EDIT: Исправлено упущение типа возвращаемого типа в комментариях. ТНХ!

EDIT: Я, кстати, не ужасаюсь вашей версией. Я не воскликнул WTF или OMG, когда увидел это. Я просто предпочитаю мой немного больше:)

Ответ 11

Мне это не особенно нравится.

Он ничего не покупает или не делает ничего более ясного, и это довольно нестандартное использование оператора.

Похоже, основное преимущество в том, что оно несколько умное. Я избегаю умных, если нет достаточно хорошей (внешней) причины, чтобы быть умным.

Ответ 12

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

Ответ 13

Прочтите раздел С++ статьи в Википедии более осторожно. Он явно перечисляет некоторые ситуации, когда использование оператора ?: является единственной опцией и не может быть заменено на if/else или switch.

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

Ответ 14

Я никогда раньше не видел ничего подобного. Хотя он умный и хорошо отформатированный, это кажется прекрасной возможностью использовать словарь/хэш-таблицу (предполагая, что Vehicle - это перечисление, которое неясно).

Ответ 15

Несколько человек уже упомянули о возможности использования типа std::map или другого ассоциативного массива для выполнения задания. Пока вы делаете это только одно место (или несколько мест), вы можете вместо этого использовать обычный массив или вектор:

Vehicle vehicles[CHAR_MAX];

// Initialization    
std::fill_n(vehicles, CHAR_MAX, feet);
vehicles['A'] = airplane;
vehicles['B'] = bus;
vehicles['C'] = car;
vehicles['H'] = horse;
vehicles['T'] = train;

// Use
Vehicle new_vehicle = vehicles[arg];

В зависимости от того, как таблицы, которые вам нужны/используют (которые хранят один и тот же тип объекта), и размер содержащихся объектов (в данном случае это автомобиль), могут быть вполне разумной альтернативой std::map. Если вы создаете много таблиц или каждый объект действительно большой, std::map становится более разумной альтернативой.

Когда вы используете std::map (или unordered_map и т.д.), вы используете больше кода для сохранения данных. Это делает обратное - но пока Транспортное средство мало (скажем, 4 байта), одна таблица, подобная выше, обычно занимает примерно половину килобайта. Трудно догадаться, насколько большой код для std::map будет для конкретного компилятора, но кажется вероятным, что он обычно будет больше половины килобайта, поэтому, если вы создаете только одну таблицу, std::map может быть чистым убытком.

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

template <class T>
class letter_table { 
    static const int range = 'Z' - 'A';

    T table[range];
public:
    // ...
    T operator[](int index) {
        index -= 'A';
        assert(index<range);
        return table[index];
    }
};

В примерном случае это даст таблицу около 100 байт - вы можете создать довольно справедливое количество 100-байтных таблиц в пространстве std::map, которое обычно занимает.

Ответ 16

Чисто практично:

Плюс: Тройная последовательность более гибкая и может использоваться для предотвращения ограничений switch, вы можете использовать другие операторы (например, < =, > =) или любые другие тесты, включая, например, сравнение строк.

x = IsEven(arg) ?  0 : 
    (arg < 0)   ? -1 : 1; // or whatever

Кроме того, если коммутатор является узким местом производительности, и у вас есть неравномерность вероятностей, вы можете принудительно выполнить наиболее вероятные тесты (из-за не оцененной гарантии для выбранного пути).

So-So В отличие от оператора switch, порядок важен (если вы не придерживаетесь ==). Это может быть преимуществом, но в остальном аналогично переключателю, который может вводить в заблуждение, когда сопровождающий незнаком с концепцией или спешит.

Многие разработчики могут уклониться, потому что они не уверены в деталях (какие условия будут оцениваться, является ли скорость операторов достаточной?). Однако, если ваш пул разработчиков не поймет хорошо представленный пример, у вас могут быть проблемы, которые не могут быть решены путем запрета троичных операторов.

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

Требуется, чтобы хорошее форматирование было легко узнаваемым (выравнивание "?" и ":" ) - отстой, когда вы используете вкладки.

Эстетика

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

Ответ 17

Просто для сравнения, в С++ 0x вы можете иметь выражение без использования условного оператора или внелинейной функции:

Vehicle new_vehicle = [&]() -> Vehicle {
    if (arg == 'B') return bus;
    if (arg == 'A') return airplane;
    if (arg == 'T') return train;
    if (arg == 'C') return car;
    if (arg == 'H') return horse;
    return feet;
}();

Однако не лучше.

Ответ 18

На мой взгляд, то, что вы сделали, приемлемо из-за простоты примера. Если вы делали больше вещей в каждом случае, этот тип конструкции мог бы быстро запутаться. По этой причине я предпочел бы переключатель или даже вложенный, если тогда elses (если их не так много), отформатирован следующим образом:

  if (A) {
      //Do A stuff
  }
  else if (B) {
      //Do B stuff
  }
  else if (C) {
      //Do C stuff
  }
  else {
      //Do default stuff
  }

Это о читаемости кода, который поддается ремонтопригодности кода. Я никогда не был большим поклонником условного оператора, потому что мне не нравится видеть несколько выражений в одной строке. Условные операторы могут быть трудными для выполнения при однократном выполнении кода в отладчике. Чем проще код, тем легче сконцентрироваться на том, что делает код.

Ответ 19

Как насчет:

enum Vehicle { bus = 'B', airplane = 'A', train, car = 'C', horse = 'H', feet = 'F' };
...
new_vehicle = arg;

:-), между прочим.

Ответ 20

Я думаю, что он полезен для кого-то, кто его кодирует, но будет трудно понять для ревиуэра,

"ХРАНИТЕ ЕГО ПРОСТОЙ БУДДИ"

Ответ 21

Многие из нас привыкли к IIF-функциям в различных инструментах отчетности или If-функции в Excel, где нам в основном нужно использовать менее понятный Iif (arg = "B"; "Bus"; Iif (arg = "А"; Самолет, "нога" )). Мне нравится ваш образец по сравнению с этим:) Я лично бы использовал if-elses, но у меня не было бы проблем с вашим образцом.