К троичному или не к троичному? [закрытый]

Я помещаю превосходный ответ 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>

у вас есть квалифицированное имя, которое относится к типу и зависит от параметра шаблона.

180
задан 7 revs, 6 users 57% 4 September 2016 в 19:54
поделиться

50 ответов

Как кто-либо выиграл бы запутываемый конкурс кода без тернарного оператора?!

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

0
ответ дан billjamesdev 23 November 2019 в 06:11
поделиться

Интересная история: Я видел, что оптимизатор взвешивает тернарный оператор как менее "тяжелый" в целях встроить, чем эквивалент если. Я заметил это с компиляторами Microsoft, но это могло быть более широко распространено.

В особенности функции как это встроили бы:

int getSomething()
{
   return m_t ? m_t->v : 0;
}

, Но это не было бы:

int getSomething() 
{
    if( m_t )
        return m_t->v;
    return 0;
}
0
ответ дан Don Neufeld 23 November 2019 в 06:11
поделиться

Мне нравится он много. Когда я использую его, я пишу его как if-then-else: одна строка каждый для условия, истинного действия и ложного действия. Тем путем я могу вложить их легко.

Пример:

x = (a == b 
     ? (sqrt(a)-2)
     : (a*a+b*b)
     );

x = (a == b 
     ? (sqrt(a)-2)
     : (a*a+b*b)
     );
x = (a == b 
     ? (c > d
        ? (sqrt(a)-2)
        : (c + cos(d))
       )
     : (a*a+b*b)
     );

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

0
ответ дан mjcohenw 23 November 2019 в 06:11
поделиться

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

int x = something == somethingElse ? 0 : -1;

у Нас на самом деле есть некоторый противный код как это в производстве... не хорошем:

int x = something == (someValue == someOtherVal ? string.Empty : "Blah blah") ? (a == b ? 1 : 2 ): (c == d ? 3 : 4);
0
ответ дан Ricardo Villamil 23 November 2019 в 06:11
поделиться

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

int i;
if( piVal ) {
    i = *piVal;
} else {
    i = *piDefVal;
}

В вышеупомянутом случае я выбрал бы троичное, потому что он имеет меньше шума:

int i = ( piVal ) ? *piVal : *piDefVal;

Аналогично условные возвращаемые значения являются хорошими кандидатами:

return ( piVal ) ? *piVal : *piDefVal;

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

, Но удобочитаемость всегда зависит от аудитории кода.

читатели должны быть в состоянии понять a ? b : c шаблон без любого умственного усилия. Если Вы не можете предположить это, пойдите для долгой версии.

0
ответ дан mar10 23 November 2019 в 06:11
поделиться

Тернарный оператор чрезвычайно полезен для того, чтобы кратко произвести списки разделенных запятой значений. Вот пример Java:

    int[] iArr = {1,2,3};
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < iArr.length; i++) {
        sb.append(i == 0 ? iArr[i] : "," + iArr[i]);
    }
    System.out.println(sb.toString());

производит: "1,2,3"

Иначе, специальное преобразование регистра для последней запятой становится раздражающим.

0
ответ дан Julien Chastang 23 November 2019 в 06:11
поделиться

При попытке уменьшить сумму строк в Вашем коде или осуществляете рефакторинг код, то пойдите для него.

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

0
ответ дан Jobo 23 November 2019 в 06:11
поделиться

Я раньше был в операторах “ternary, делают строку un-readable” лагерем, но в последние несколько лет I’ve, выращенный для симпатии их при использовании умеренно. Однострочные тернарные операторы могут увеличить удобочитаемость, если все в Вашей команде понимают продолжение what’s. It’s краткий способ сделать что-то без издержек большого количества фигурных скобок ради фигурных скобок.

два случая, где я don’t как они: если они идут также далеко вне метки на 120 столбцов или если они встраиваются в другие тернарные операторы. Если Вы can’t быстро, легко и четко выражаете что you’re, делающий в тернарном операторе. Затем используйте, если/еще эквивалентный.

0
ответ дан Joe Basirico 23 November 2019 в 06:11
поделиться

Это зависит :)

Они полезны при контакте с возможно нулевыми ссылками (btw: Java действительно нужен способ легко сравнить две возможно пустых строки).

проблема начинается, когда Вы - вложение много тернарных операторов в одном выражении.

0
ответ дан 23 November 2019 в 06:11
поделиться

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

0
ответ дан Denis Hennessy 23 November 2019 в 06:11
поделиться

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

Что-то вроде этого было бы действительно сбивающее с толку, хотя эффективный, способ использовать их:

 __CRT_INLINE int __cdecl getchar (void)
{
   return (--stdin->_cnt >= 0)
          ?  (int) (unsigned char) *stdin->_ptr++
          : _filbuf (stdin);
}

Однако это:

c = a > b ? a : b;

совершенно разумно.

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

0
ответ дан Onion-Knight 23 November 2019 в 06:11
поделиться

представить someSay в виде строки = bCanReadThis? "Нет": "Да";

0
ответ дан Steven A. Lowe 23 November 2019 в 06:11
поделиться

В малых дозах они могут сократить количество строк и сделать код более читаемым; особенно, если результат - что-то как установка символьной строки к "Да" или "Нет" на основе результата вычисления.

Пример:

char* c = NULL;
if(x) {
  c = "true";
}else {
  c = "false";
}

по сравнению с:

char* c = x ? "Yes" : "No";

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

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

Во втором примере строка покажет как выполняемый независимо от значения X, таким образом, Вы не сможете быть уверены, что протестировали обходной путь (YMMV в зависимости от способности Ваших инструментов покрытия).

Это имеет значение больше с увеличивающейся сложностью тестов.

0
ответ дан Adam Hawes 23 November 2019 в 06:11
поделиться

Я - большой поклонник его... в надлежащих случаях.

Материал как здорово и, лично, мне не также трудно читать/понимать:

$y = ($x == "a" ? "apple"
   : ($x == "b" ? "banana"
   : ($x == "c" ? "carrot"
   : "default")));

я знаю, что, вероятно, заставляет много людей съежиться, все же.

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

class Foo {
    var $bar;
    function Foo() {
        $this->bar = "original value";
    }
    function &tern() {
        return true ? $this->bar : false;
    }
    function &notTern() {
        if (true) return $this->bar;
        else      return false;
    }
}

$f = new Foo();
$b =& $f->notTern();
$b = "changed";
echo $f->bar;  // "changed"

$f2 = new Foo();
$b2 =& $f->tern();
$b2 = "changed";
echo $f2->bar;  // "original value"
-1
ответ дан nickf 23 November 2019 в 06:11
поделиться

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

int c = a < b ? a : b;

является "более сложным", чем эквивалент (но более подробным):

int c;
if (a < b) {
    c = a;
} else {
    c = b;
}

или еще более неловкое (который я видел):

int c = a;
if (!a < b) {
    c = b;
}

Тем не менее взгляд тщательно на Ваши альтернативы в зависимости от конкретного случая. При принятии propoerly-образованного разработчика спросите, который наиболее кратко выражает намерение кода, и пойдите с тем.

0
ответ дан joel.neely 23 November 2019 в 06:11
поделиться

Мое недавно сформулированное эмпирическое правило для определения того, следует ли вам использовать тернарный оператор:

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

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

1
ответ дан 23 November 2019 в 06:11
поделиться

One reason noone seems to mention for using the ternary operator, at least in languages like D that support type inference is to allow type inference to work for amazingly complicated template types.

auto myVariable = fun();  
// typeof(myVariable) == Foo!(Bar, Baz, Waldo!(Stuff, OtherStuff)).

// Now I want to declare a variable and assign a value depending on some
// conditional to it.
auto myOtherVariable = (someCondition) ? fun() : gun();

// If I didn't use the ternary I'd have to do:
Foo!(Bar, Baz, Waldo!(Stuff, OtherStuff)) myLastVariable;  // Ugly.
if(someCondition) {
    myLastVariable = fun();
} else {
    myLastVariable = gun():
}
0
ответ дан 23 November 2019 в 06:11
поделиться

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

Недавно я наткнулся на эту строку в некотором открытом исходном коде, над изменением которого я работаю.

where 
               (active == null ? true : 
               ((bool)active ? p.active : !p.active)) &&... 

Вместо

where ( active == null || p.active == active) &&...

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

0
ответ дан 23 November 2019 в 06:11
поделиться

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

Я часто использую тернарный оператор во встроенном коде, чтобы прояснить, что делает мой код. Возьмите следующие (упрощенные для ясности) образцы кода:

Фрагмент 1:

int direction = read_or_write(io_command);

// Send an I/O
io_command.size = (direction==WRITE) ? (32 * 1024) : (128 * 1024);
io_command.data = &buffer;
dispatch_request(io_command);

Фрагмент 2:

int direction = read_or_write(io_command);

// Send an I/O
if (direction == WRITE) {
    io_command.size = (32 * 1024);
    io_command.data = &buffer;
    dispatch_request(io_command);
} else {
    io_command.size = (128 * 1024);
    io_command.data = &buffer;
    dispatch_request(io_command);
}

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

У тернарного оператора есть еще одно преимущество (хотя обычно оно возникает только во встроенном ПО). Некоторые компиляторы могут выполнять определенные оптимизации только в том случае, если код не «вложен» за определенную глубину (то есть внутри функции вы увеличиваете глубину вложенности на 1 каждый раз, когда вводите оператор if, loop или switch, и уменьшаете ее на 1, когда вы оставите это). Иногда использование тернарного оператора может минимизировать объем кода, который должен находиться внутри условного выражения (иногда до такой степени, что компилятор может оптимизировать условное выражение) и может уменьшить глубину вложенности вашего кода. В некоторых случаях мне удавалось реструктурировать некоторую логику с помощью тернарного оператора (как в моем примере выше) и уменьшить глубину вложенности функции настолько, чтобы компилятор мог выполнить дополнительные шаги по оптимизации. По общему признанию, это довольно узкий вариант использования, но я решил, что о нем все равно стоит упомянуть.

0
ответ дан 23 November 2019 в 06:11
поделиться

Тернарный оператор передает. Они не сложны, если вы правильно отформатируете. Возьмем пример високосного года из @paxdiablo:

$isLeapYear = 
   (($year % 400) == 0)
   ? 1
   : ((($year % 100) == 0)
      ? 0
      : ((($year % 4) == 0)  
         ? 1 
         : 0));

Это можно написать более кратко и сделать его более читаемым с помощью этого форматирования:

//--------------test expression-----result
$isLeapYear = (($year % 400) == 0) ? 1 : 
              ((($year % 100) == 0)? 0 : 
              ((($year % 4) == 0)  ? 1 : 
                                     0));//default result
1
ответ дан 23 November 2019 в 06:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: