Я помещаю превосходный ответ JLBorges на аналогичный вопрос дословно из cplusplus.com, так как это наиболее краткое объяснение, которое я прочитал по этому вопросу.
] В шаблоне, который мы пишем, есть два типа имен, которые можно использовать - зависимые имена и не зависимые имена. Зависимое имя - это имя, которое зависит от параметра шаблона; неизменяемое имя имеет то же значение, независимо от параметров шаблона.
Например:
template< typename T > void foo( T& x, std::string str, int count ) { // these names are looked up during the second phase // when foo is instantiated and the type T is known x.size(); // dependant name (non-type) T::instance_count ; // dependant name (non-type) typename T::iterator i ; // dependant name (type) // during the first phase, // T::instance_count is treated as a non-type (this is the default) // the typename keyword specifies that T::iterator is to be treated as a type. // these names are looked up during the first phase std::string::size_type s ; // non-dependant name (type) std::string::npos ; // non-dependant name (non-type) str.empty() ; // non-dependant name (non-type) count ; // non-dependant name (non-type) }
То, что зависит от зависимого имени, может быть чем-то другим для каждого конкретного экземпляра шаблона. Как следствие, шаблоны C ++ подвержены «двухфазному поиску имен». Когда шаблон сначала анализируется (до того, как выполняется какое-либо создание), компилятор просматривает не зависящие имена. Когда происходит конкретное создание шаблона, параметры шаблона известны к тому времени, и компилятор ищет зависимые имена.
На первом этапе анализатор должен знать, является ли зависимое имя именем типа или имени не-типа. По умолчанию зависимым именем считается имя не-типа.
Использовать ключевое слово typename только в объявлениях шаблонов и определениях, приведенных ниже.
blockquote>у вас есть квалифицированное имя, которое относится к типу и зависит от параметра шаблона.
Используйте его для простые выражения [только 116]:
int a = (b > 10) ? c : d;
не объединяют в цепочку или вложенное множество тернарные операторы как он трудно для чтения и сбивающий с толку:
int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8;
, Кроме того, при использовании тернарного оператора, рассматривают форматирование кода способом, которые улучшают удобочитаемость:
int a = (b > 10) ? some_value
: another_value;
Если Вы и Ваши коллеги понимаете то, что они делают и они не создаются в крупных группах, я думаю, что они делают код менее сложным и легче читать, потому что существует просто меньше кода.
единственное время я думаю, что тернарные операторы делают код тяжелее для понимания, когда у Вас есть больше чем 3 или 4 в одной строке. Большинство людей не помнит, что они - основанный на праве приоритет и когда у Вас есть стек их, он делает чтение кода кошмаром.
Для простых задач как присвоение другого значения в зависимости от условия они являются великими. Я не использовал бы их, когда существуют более длительные выражения в зависимости от условия tho.
Столько отвечает, сказали, это зависит . Я нахожу что, если троичное сравнение не видимо на быстром сканировании вниз код, то это не должно использоваться.
Как второстепенный вопрос, я мог бы также отметить, что его самое существование является на самом деле чем-то вроде anomoly вследствие того, что в C, сравнительное испытание является оператором. В Значке if
конструкция (как большая часть Значка) является на самом деле выражением. Таким образом, можно сделать вещи как:
x[if y > 5 then 5 else y] := "Y"
..., который я нахожу намного более читаемыми, чем троичный оператор сравнения. :-)
была дискуссия недавно о возможности добавления ?:
оператор к Значку, но несколько человек правильно указали, что не было абсолютно никакой потребности из-за пути if
работы.
, Что означает, что, если Вы могли бы сделать это в C (или любой из других языков, которые имеют троичный оператор), затем Вам, на самом деле, не был бы нужен троичный оператор вообще.
Объединенный в цепочку все хорошо с - вложенный, не так.
я склонен использовать их больше в C просто b/c, они, если оператор, который имеет значение, таким образом, это сокращает ненужное повторение или переменные:
x = (y < 100) ? "dog" :
(y < 150) ? "cat" :
(y < 300) ? "bar" : "baz";
, а не
if (y < 100) { x = "dog"; }
else if (y < 150) { x = "cat"; }
else if (y < 300) { x = "bar"; }
else { x = "baz"; }
В присвоениях как это, я нахожу, что это меньше для рефакторинга, и более ясный.
, Когда я работаю в рубине, с другой стороны, я, более вероятно, буду использовать if...else...end
, потому что это - выражение также.
x = if (y < 100) then "dog"
elif (y < 150) then "cat"
elif (y < 300) then "bar"
else "baz"
end
(хотя, по общему признанию, для чего-то это простое, я мог бы просто использовать тернарный оператор так или иначе).
Оператор Ternary ?:
является просто функциональным эквивалентом процедурного if
конструкция. Таким образом, пока Вы не используете вложенный ?:
выражения, аргументы в пользу функционального представления любой операции применяются здесь. Но вложенные троичные операции могут привести к коду, который совершенно сбивает с толку (осуществление для читателя: попытайтесь писать синтаксический анализатор, который обработает вложенные троичные условные выражения, и Вы будете ценить их сложность).
, Но существует много ситуаций, где консервативное использование ?:
оператор может привести к коду, который является на самом деле легче для чтения, чем иначе. Например:
int compareTo(Object object) {
if((isLessThan(object) && reverseOrder) || (isGreaterThan(object) && !reverseOrder)) {
return 1;
if((isLessThan(object) && !reverseOrder) || (isGreaterThan(object) && reverseOrder)) {
return -1;
else
return 0;
}
Теперь сравнивают это с этим:
int compareTo(Object object) {
if(isLessThan(object))
return reverseOrder ? 1 : -1;
else(isGreaterThan(object))
return reverseOrder ? -1 : 1;
else
return 0;
}
, Поскольку код более компактен он, там меньше синтаксического шума, и при помощи тернарного оператора рассудительно (который находится только в отношении с свойство reverseOrder ), конечный результат не является особенно кратким.
Это - вопрос стиля, действительно; подсознательные правила, за которыми я склонен следовать:
foo = (bar > baz) ? true : false
, но НЕ foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
<%= (foo) ? "Yes" : "No" %>
(foo) ? FooIsTrue(foo) : FooIsALie(foo)
) мне нравится он, потому что это кратко и изящно для простых операций присвоения.
Как столько вопросов о мнении, ответ неизбежно: это зависит
Для чего-то как:
return x ? "Yes" : "No";
я думаю, что это очень более кратко (и более быстрый, чтобы я проанализировал), чем:
if (x) {
return "Yes";
} else {
return "No";
}
Теперь, если Ваше условное выражение сложно, то троичная операция не является хорошим выбором. Что-то как:
x && y && z >= 10 && s.Length == 0 || !foo
не хороший кандидат на тернарный оператор.
Как в стороне, если Вы - программист C, GCC на самом деле имеет расширение , который позволяет Вам исключать если - истинная часть троичного, как это:
/* 'y' is a char * */
const char *x = y ? : "Not set";
, Который установит x
на y
, принятие y
не NULL
. Хороший материал.
В моем уме только имеет смысл использовать тернарный оператор в случаях, где выражение необходимо.
В других случаях, это походит на ясность уменьшений тернарного оператора.
Мерой цикломатическая сложность , использование if
операторы или тернарный оператор эквивалентны. Таким образом той мерой, ответ никакой , сложность была бы точно тем же как прежде.
другими мерами, такими как удобочитаемость, пригодность для обслуживания и DRY (Don't-Repeat-Yourself), любой выбор может оказаться лучше, чем другой.
Я использую его довольно часто в местах, где я вынужден работать в конструкторе - например, новая.NET 3.5 LINQ к конструкциям XML - для определения значений по умолчанию, когда дополнительный параметр является пустым.
Изобретенный пример:
var e = new XElement("Something",
param == null ? new XElement("Value", "Default")
: new XElement("Value", param.ToString())
);
или (благодарит астерит)
var e = new XElement("Something",
new XElement("Value",
param == null ? "Default"
: param.ToString()
)
);
, Неважно, ли Вы используете тернарный оператор или нет, удостоверяясь, Ваш код читаем, важная вещь. Любая конструкция может быть сделана нечитабельной.
Я использую тернарный оператор, где когда-либо я могу, если он не делает код чрезвычайно трудно для чтения, но затем это - обычно просто признак, что мой код мог использовать немного рефакторинга.
Это всегда озадачивает меня, как некоторые люди думают, что тернарный оператор является "скрытой" функцией или является несколько таинственным. Это - одна из первых вещей, которые я изучил, когда я начинаю программировать в C, и я не думаю, что это уменьшает удобочитаемость вообще. Это - естественная часть языка.
Я соглашаюсь с jmulder: это не должно использоваться вместо if
, но это имеет свое место для выражения возврата или в выражении:
echo "Result: " + n + " meter" + (n != 1 ? "s" : "");
return a == null ? "null" : a;
Первый - просто пример, лучшая i18n поддержка множественного числа должна использоваться!
Мне нравится особый случай Groovy тернарного оператора, названного оператором Elvis:?:
expr ?: default
Этот код оценивает к expr, если это не является пустым, и по умолчанию, если это. Технически это не действительно тернарный оператор, но это определенно связано с ним и экономит много времени.
Если Вы используете тернарный оператор для простого условного присвоения, я думаю, что он прекрасен. Я видел, что это (ab), привыкший к управляющей программе, течет, даже не делая присвоение, и я думаю, что этого нужно избежать. Используйте если оператор в этих случаях.
Я думаю, что тернарный оператор должен использоваться при необходимости. Это - очевидно, очень субъективный выбор, но я нахожу, что простое выражение (особенно как выражение возврата) намного более ясно, чем полный тест. Пример в C/C++:
return (a>0)?a:0;
По сравнению с:
if(a>0) return a;
else return 0;
у Вас также есть случай, где решение между тернарным оператором и созданием функции. Например, в Python:
l = [ i if i > 0 else 0 for i in lst ]
альтернатива:
def cap(value):
if value > 0:
return value
return 0
l = [ cap(i) for i in lst ]
необходимо достаточно, чтобы в Python (как пример), такая идиома регулярно была видна:
l = [ ((i>0 and [i]) or [0])[0] for i in lst ]
эта строка использует свойства логических операторов в Python: они ленивы, и возвращает последнее значение, вычисленное, если это равно конечному состоянию.
Мне нравятся они. Я не знаю, почему, но я чувствую себя очень спокойным, когда я использую троичное выражение.
Я видел таких зверей как (это было на самом деле намного хуже, так как это было isValidDate и проверило месяц и день также, но я не мог быть побеспокоен, пытаясь помнить все это):
isLeapYear =
((yyyy % 400) == 0)
? 1
: ((yyyy % 100) == 0)
? 0
: ((yyyy % 4) == 0)
? 1
: 0;
, где, явно, серия операторов "if" была бы лучше (хотя это еще лучше, чем макро-версия я однажды видел).
я не возражаю против него для мелочей как:
reportedAge = (isFemale && (Age >= 21)) ? 21 + (Age - 21) / 3 : Age;
или даже немного хитрые вещи как:
printf ("Deleted %d file%s\n", n, (n == 1) ? "" : "s");
Мне нравится использовать оператор в коде отладки для печати ошибочных значений, таким образом, я не должен искать их все время. Обычно я делаю это для печати отладки, которая не собирается оставаться, как только я сделан, разработав.
int result = do_something();
if( result != 0 )
{
debug_printf("Error while doing something, code %x (%s)\n", result,
result == 7 ? "ERROR_YES" :
result == 8 ? "ERROR_NO" :
result == 9 ? "ERROR_FILE_NOT_FOUND" :
"Unknown");
}
Я почти никогда не использую тернарный оператор, потому что каждый раз, когда я ДЕЙСТВИТЕЛЬНО использую его, он всегда заставляет меня думать намного больше, чем я имею к позже, когда я пытаюсь поддержать его.
мне нравится избегать многословия, но когда оно сделает код намного легче взять, я пойду для многословия.
Рассмотрите:
String name = firstName;
if (middleName != null) {
name += " " + middleName;
}
name += " " + lastName;
Теперь, который является немного подробным, но я нахожу его намного более читаемым, чем:
String name = firstName + (middleName == null ? "" : " " + middleName)
+ " " + lastName;
или:
String name = firstName;
name += (middleName == null ? "" : " " + middleName);
name += " " + lastName;
Это просто, кажется, сжимает слишком много информации в слишком небольшое пространство, не проясняя, что продолжается. Каждый раз я вижу используемый тернарный оператор, я всегда находил альтернативу, которая казалась намного легче читать... с другой стороны, который является чрезвычайно субъективным мнением, поэтому если Вы и Ваши коллеги находите троичными очень читаемый, пойдите для него.
Ну, синтаксис для него неприятен. Я нахожу функциональную IFS очень полезной, и часто делает код более читаемым.
я предложил бы делать макрос для создания его более читаемым, но я уверен, что кто-то может придумать ужасный пограничный случай (как всегда существует с CPP).
Только, когда:
$var = (простой> тест? simple_result_1: simple_result_2);
KISS.
Я обычно использую в вещах как это:
before:
if(isheader)
drawtext(x,y,WHITE,string);
else
drawtext(x,y,BLUE,string);
after:
drawtext(x,y,isheader==true?WHITE:BLUE,string);
Поскольку другие указали, что они хороши для коротких простых условий. Мне особенно нравятся они за значения по умолчанию (отчасти как || и или использование в JavaScript и Python), например,
int repCount = pRepCountIn ? *pRepCountIn : defaultRepCount;
, Другое общее использование должно инициализировать ссылку в C++. Так как ссылки должны быть объявлены и инициализированы в том же операторе, который Вы не можете использовать если оператор.
SomeType& ref = pInput ? *pInput : somethingElse;
Я рассматриваю тернарные операторы много как GOTO. У них есть свое место, но они - что-то, что необходимо обычно стараться не делать код легче понять.
Я недавно видел изменение на тернарных операторах (хорошо, вид), которые делают стандарт" ()?": вариант, кажется, образец ясности:
var Result = [CaseIfFalse, CaseIfTrue][(boolean expression)]
или, для предоставления более материального примера:
var Name = ['Jane', 'John'][Gender == 'm'];
Мышление Вы, это - JavaScript, таким образом, вещи как этот не могли бы быть возможными на других языках (к счастью).
Для простого, если случаи, мне нравится использовать его. На самом деле намного легче читать/кодировать, например, как параметры для функций или подобных вещей. Также для предотвращения новой строки мне нравится сохранять со всеми мой если/еще.
Neseting это было бы большое НЕТ - НЕТ в моей книге.
Так, возобновление, для сингла, если/еще я буду использовать тернарный оператор. Для других случаев постоянный клиент, если/еще, если/еще (или переключатель)
Я люблю их, особенно на безопасных с точки зрения типов языках.
я не вижу как это:
int count = (condition) ? 1 : 0;
немного тяжелее, чем это:
int count;
if (condition)
{
count = 1;
}
else
{
count = 0;
}
редактирование -
я утверждал бы, что тернарные операторы делают все менее сложным и более аккуратным, чем альтернатива.
Это делает отладку немного более трудной, так как Вы не можете поместить точки останова в каждое из sub выражений. Я редко использую его.
Нет. Их трудно считать. Если/Еще намного легче читать.
Это - мое мнение. Ваш пробег может варьироваться.