Здравствуйте, CreatorCray, Вы писали:
Pzz>>(a ? add : remove)( (y ? a : b)[ z ? c : d ] ); CC>Да здравствует обфускация!
ИМХО код вполне читается, а так же самодокументирован: не лезь а то убъёт!
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
За тернарный оператор:
— позволяет запихнуть всё в одно выражение
— позволяет избежать присваиваний, заменяя их конструированием
— позволяет использовать временные объекты, это полезно для RVO (которое любят компиляторы; тогда как NRVO им даётся с бОльшим трудом)
const Foo x (a() ? b() : c()); // даже copy constructible может не потребоваться
foo(d() ? e() : f());
// versus
/*nonconst*/Foo x; // default constructible, assignableif(a()) x = b(); else x = c();
if(d()) foo(e()); else foo(f());
За if на разных строчках:
— позволяет ставить брекпоинты на ветках
— не требует однотипности веток
За if на одной строчке:
— кр-сть — с-а т.!
Короче говоря, однострочный if — это худший вариант.
Как из двух "implicit conversion sequences" найти наилучшую описывается здесь
13.3.3.2 Ranking implicit conversion sequences
Standard conversion sequences are ordered by their ranks: an Exact Match is a better conversion than a Promotion,
which is a better conversion than a Conversion.
В двух словах: так как Promotion лучше, чем Conversion, то будет применяться Integral promotion и bool продвинется до int.
Здравствуйте, Begemot_, Вы писали:
B_>Почему так не пишут или я ошибаюсь и это нормально и принято?
Предпочитаю использовать тернарный оператор, если речь идет только о возвращении значения и условный оператор, если имеются побочные эффекты.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>А так еще лучше
PD>(x ? add : remove) (t ? a : b);
PD>после чего читающий этот код долго чешет в затылке, пытаясь понять, что же сделали и с чем.
Какие сложности? В зависимости от x выбирается функтор, а зависимости от t — его аргумент. Своеобразный такой сurrying на C
Чесать в затылке лично мне приходится думая "как это переписать на if", "как поддерживать такой if"...
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, gear nuke, Вы писали:
PD>>(x ? add : remove) (t ? a : b);
PD>>после чего читающий этот код долго чешет в затылке, пытаясь понять, что же сделали и с чем.
GN>Какие сложности? В зависимости от x выбирается функтор, а зависимости от t — его аргумент. Своеобразный такой сurrying на C
Между прочим, если бы у "функтора" был не один аргумент, а пяток, то так по-моему сильно понятнее выглядит, отдельно выбирать функцию в зависимости от обстановки, а потом одним махом вызывать уже выбраную. Иначе приходится дублировать вычисление аргументов, со всеми вытекающими прелестями копипасты.
Если бы вариантов было не два, а больше, имело бы смысл завести указатель на функцию, вычислить его, а потом позвать.
U>Как из двух "implicit conversion sequences" найти наилучшую описывается здесь
13.3.3.2 Ranking implicit conversion sequences
U>
U>Standard conversion sequences are ordered by their ranks: an Exact Match is a better conversion than a Promotion,
U>which is a better conversion than a Conversion.
U>В двух словах: так как Promotion лучше, чем Conversion, то будет применяться Integral promotion и bool продвинется до int.
Курить стандартик надо с умом, а то ведь ненароком и обкуриться можно.
Если TRUE имеет тип int, то в сравнении TRUE == true какие-либо implicit conversion sequences не рассматриваются вообще.
C++03 — 13.3.3.1/1:
An implicit conversion sequence is a sequence of conversions used to convert an argument in a function call to the type of the corresponding parameter of the function being called.
Operator functions рассматриваются только если хотя бы один из операндов имеет классовый или перечислительный тип:
13.3.1.2 Operators in expressions /2:
If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator. In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator. Therefore, the operator notation is first transformed to the equivalent function-call notation as summarized in Table 8
В данном же случае следует руководствоваться исключительно правилами для встроенных операторов, описанными в разделе 5:
13.3.1.2/1:
If no operand of an operator in an expression has a type that is a class or an enumeration, the operator is assumed to be a built-in operator and interpreted according to clause 5.
5.10/1:
The == (equal to) and the != (not equal to) operators have the same semantic restrictions, conversions, and result type as the relational operators except for their lower precedence and truth-value result.
5.9 Relational operators /2:
The usual arithmetic conversions are performed on operands of arithmetic or enumeration type.
5/9:
Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:
— If either operand is of type long double, the other shall be converted to long double.
— Otherwise, if either operand is double, the other shall be converted to double.
— Otherwise, if either operand is float, the other shall be converted to float. — Otherwise, the integral promotions (4.5) shall be performed on both operands. [Footnote: As a consequence, operands of type bool, wchar_t, or an enumerated type are converted to some integral type]
— Then, if either operand is unsigned long the other shall be converted to unsigned long.
— Otherwise, if one operand is a long int and the other unsigned int, then if a long int can represent all the values of an unsigned int, the unsigned int shall be converted to a long int; otherwise both operands shall be converted to unsigned long int.
— Otherwise, if either operand is long, the other shall be converted to long.
— Otherwise, if either operand is unsigned, the other shall be converted to unsigned.
4.5 Integral promotions /4:
An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true becoming one.
Здравствуйте, igna, Вы писали:
U>>Пожалуй, не соглашусь. Вроде bool должен сконвертроваться в int. I>Вот именно, что вроде.
Что тебе мешает проверить?
U>>Чтобы узнать кто куда конвертится, надо курить
4 Standard conversions
I>Ну так кури. 4.12.
Ты путаешь что во что конвертируется.
4.5 Integral promotions
4. An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true
becoming one.
4.7 Integral conversions
4. If the destination type is bool, see 4.12. If the source type is bool, the value false is converted to zero
and the value true is converted to one.
if (int == bool)
if (bool == int)
сначала они приводятся к одному типу (т.е. к int) т.к. они оба являются параметрами operator==.
Ну а потом уже operator== возвращает bool.
Так что bool тут является source type
Здравствуйте, igna, Вы писали:
I>Здравствуйте, CreatorCray, Вы писали:
CC>>И, ты уж звиняй, но первый вариант лично я отношу исключительно к индусокоду.
I>А такой не относишь?:
I>
I>x ? add(t) : remove(t);
I>
I>Речь конечно не о том случае, когда add и remove возвращают значение, которое затем в программе используется, а о том, когда вышеприведенная конструкция используется вместо if.
(x == true) ? add(t) : remove(t); // это нормальный код, кратко и по теме.
Здравствуйте, vpchelko, Вы писали:
_>>>>у меня еще с чистого C неприятие прямого сравнения с true. != false или в данном случае вообще if (x) гораздо лучше. I>>>Чем же сравнение с false лучше сравнения с true? CC>>Тем, что только ноль == false. А за true принимается любое ненулевое значение.
V>С какой такой стати? false и true это константы.
В С++ есть тип bool и у него есть два значения: true и false, константы, да
В С булевского типа изначально не было в принципе (В С99 добавили stdbool, но это не встроенный тип). Равно как и true/false констант.
Здравствуйте, Begemot_, Вы писали:
B_>Почему так не пишут или я ошибаюсь и это нормально и принято?
Я в своём коде использую только для возвращаемоего параметра. 1 условия с else имеют свойство разрастаться, к томуже 2 не поставить бряку на ветку, просто тупо чтобы не путать 3 (тернальный на возвращаемое только), 4 чтобы иметь одинакое строение условий везде (не везде есть else, как то тупо в одном месте писать x ? foo1() : foo2(); а во втором if ( x ) foo(); )
Вот такие причины лично у меня.
Резюме:
1. Если тебя это не смущает, то пользуйся на здоровье
2. Если у тебя тревожно на душе из-за такого написания, то не пиши так и спи спокойно
Здравствуйте, gear nuke, Вы писали:
Pzz>>>(a ? add : remove)( (y ? a : b)[ z ? c : d ] ); CC>>Да здравствует обфускация!
GN>ИМХО код вполне читается, а так же самодокументирован: не лезь а то убъёт!
А это мысль! А то у меня часто возникает обратная проблема: лезут, а убивать приходится мне, а у меня для этого характер слишком мягкий
Здравствуйте, Begemot_, Вы писали:
B_>Почему так не пишут или я ошибаюсь и это нормально и принято?
ИМХО тренарный оператор используем там, где он позволяет избежать дублирования кода и повысить читаемость, например:
longName = very_very_very_long_function_name (argumentOne, argumentTwo, flag ? number : 45);
т.е. четко видно, чем отличаются ветки (в отличие от if/else).
В случае с return он позволяет избежать дублирования слова return Ну и сэкономить 3 строчки при строгом стиле кодирования (4 строки на if/else) и одну при "самом строгом" (3 строки на тренарный оператор)
Здравствуйте, Begemot_, Вы писали:
B_> Нет, тут уже подмена понятий.
Да? И каких?
if (e1) e2; вычисляет e1, затем в зависимости от результата вычисляет или не вычисляет e2. e1 && e2 выполняет те же действия плюс имеет значение. Отбрасывание вычисленного значения в C/C++ используется постоянно. А вот e1 ? e2 : e3 в отличие от if (e1) e2; else e3; не только имеет значение, но и выполняет преобразование типа.
Я собственно не за и не против замены if выражениями, но не согласен с тем, что ?: в каком-то объективном смысле лучше чем &&.
Ничуть.
И, ты уж звиняй, но первый вариант лично я отношу исключительно к индусокоду.
И написавшего такое в production code буду крайне жестоко отучать так делать впредь.
Здравствуйте, CreatorCray, Вы писали:
CC>И, ты уж звиняй, но первый вариант лично я отношу исключительно к индусокоду.
А такой не относишь?:
x ? add(t) : remove(t);
Речь конечно не о том случае, когда add и remove возвращают значение, которое затем в программе используется, а о том, когда вышеприведенная конструкция используется вместо if.
Здравствуйте, igna, Вы писали:
CC>>Такой тоже отношу. I>Чтож ответил не на оригинальный пост, а куда-то набок невпопад?
Потому как x && add(t); хуже чем то, что предлагалось в исходном посте, не удержался.
Я не уверен что в этом случае компилятор сможет сделать inlining если что.
Ну и для методов это работать не будет. Вернее будет, но запись получится очень громоздкой.
Здравствуйте, igna, Вы писали:
I>И кстати, я ведь не предлагал использовать && вместо if, а задавал вопрос автору темы.
Ну сорри, не заметил знак вопроса — слишком он оторван от тела сообщения.
Здравствуйте, mike_rs, Вы писали:
_>Здравствуйте, vpchelko, Вы писали:
V>>(x == true) ? add(t) : remove(t); // это нормальный код, кратко и по теме.
_>у меня еще с чистого C неприятие прямого сравнения с true. != false или в данном случае вообще if (x) гораздо лучше.
Ни чего тут неприятного не вижу. Всегда лучше явно написать с чем сравниваешь.
А == true или != false это уж зависит от стиля текущего проекта.
Да как тебе сказать... Всегда лучше явно написать что сравниваешь.
А (x ? true : false) или (!x ? false : true) это уж зависит от стиля текущего проекта.
V>>Это уже жжж, зачем такое нужно?
I>Да как тебе сказать... Всегда лучше явно написать что сравниваешь. I>А (x ? true : false) или (!x ? false : true) это уж зависит от стиля текущего проекта.
Ответь зачем 2 раза сравнивать?
Это ((x ? true : false) == true) ? add(t) : remove(t); Че это такое?
Если это расписать if / else...
if (x)
{
if(true == true)
{
add(t);
}
// else (X_x);
}
else
{
// if(true == false) (x_X)
remove(t);
} // ну типо я сам руками с оптимизирован.
Здравствуйте, vpchelko, Вы писали:
V>Ответь зачем 2 раза сравнивать?
Там строго говоря одно сравнение и две проверки. Если же ты под сравнением понимаешь собственно сравнение или проверку, то в моем примере три сравнения, а в твоем было два. А достаточно одного.
Здравствуйте, igna, Вы писали:
_>>у меня еще с чистого C неприятие прямого сравнения с true. != false или в данном случае вообще if (x) гораздо лучше. I>Чем же сравнение с false лучше сравнения с true?
Тем, что только ноль == false. А за true принимается любое ненулевое значение.
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, igna, Вы писали:
_>>>у меня еще с чистого C неприятие прямого сравнения с true. != false или в данном случае вообще if (x) гораздо лучше. I>>Чем же сравнение с false лучше сравнения с true? CC>Тем, что только ноль == false. А за true принимается любое ненулевое значение.
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, igna, Вы писали:
_>>>у меня еще с чистого C неприятие прямого сравнения с true. != false или в данном случае вообще if (x) гораздо лучше. I>>Чем же сравнение с false лучше сравнения с true? CC>Тем, что только ноль == false. А за true принимается любое ненулевое значение.
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, vpchelko, Вы писали:
_>>>>>у меня еще с чистого C неприятие прямого сравнения с true. != false или в данном случае вообще if (x) гораздо лучше. I>>>>Чем же сравнение с false лучше сравнения с true? CC>>>Тем, что только ноль == false. А за true принимается любое ненулевое значение.
V>>С какой такой стати? false и true это константы. CC>В С++ есть тип bool и у него есть два значения: true и false, константы, да CC>В С булевского типа изначально не было в принципе (В С99 добавили stdbool, но это не встроенный тип). Равно как и true/false констант.
CC>помедитируй над таким вот кодом. CC>
Здравствуйте, igna, Вы писали:
I>Стой, куда! Нет, ты уж приведи пример, в котором сравнение с false нельзя заменить на сравнение с true!
На.
// If the function succeeds, the return value is nonzero.
// If the function fails, the return value is zero.
BOOL WINAPI CheckTokenMembership(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, igna, Вы писали:
I>>Стой, куда! Нет, ты уж приведи пример, в котором сравнение с false нельзя заменить на сравнение с true!
CC>На. CC>
CC>// If the function succeeds, the return value is nonzero.
CC>// If the function fails, the return value is zero.
CC>BOOL WINAPI CheckTokenMembership(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
CC>
Здравствуйте, vpchelko, Вы писали:
_>>>>>>у меня еще с чистого C неприятие прямого сравнения с true. != false или в данном случае вообще if (x) гораздо лучше. I>>>>>Чем же сравнение с false лучше сравнения с true? CC>>>>Тем, что только ноль == false. А за true принимается любое ненулевое значение.
V>>>С какой такой стати? false и true это константы. CC>>В С++ есть тип bool и у него есть два значения: true и false, константы, да CC>>В С булевского типа изначально не было в принципе (В С99 добавили stdbool, но это не встроенный тип). Равно как и true/false констант.
CC>>помедитируй над таким вот кодом.
V>Так зачем ты пишешь про true и false, которых в С нет?
в С нет встроенного типа bool, но булевы операции есть.
в С++ при конвертации в bool работают правила: == 0 -> false, != 0 -> true
CC>>// If the function succeeds, the return value is nonzero.
CC>>// If the function fails, the return value is zero.
CC>>BOOL WINAPI CheckTokenMembership(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
CC>>
V>Ровняй BOOL на TRUE и FALSE.
Что ты этим хотел сказать?
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, vpchelko, Вы писали:
CC>>>На. CC>>>
CC>>>// If the function succeeds, the return value is nonzero.
CC>>>// If the function fails, the return value is zero.
CC>>>BOOL WINAPI CheckTokenMembership(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
CC>>>
V>>Ровняй BOOL на TRUE и FALSE. CC>Что ты этим хотел сказать?
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, vpchelko, Вы писали:
_>>>>>>>у меня еще с чистого C неприятие прямого сравнения с true. != false или в данном случае вообще if (x) гораздо лучше. I>>>>>>Чем же сравнение с false лучше сравнения с true? CC>>>>>Тем, что только ноль == false. А за true принимается любое ненулевое значение.
V>>>>С какой такой стати? false и true это константы. CC>>>В С++ есть тип bool и у него есть два значения: true и false, константы, да CC>>>В С булевского типа изначально не было в принципе (В С99 добавили stdbool, но это не встроенный тип). Равно как и true/false констант.
CC>>>помедитируй над таким вот кодом.
V>>Так зачем ты пишешь про true и false, которых в С нет? CC>в С нет встроенного типа bool, но булевы операции есть. CC>в С++ при конвертации в bool работают правила: == 0 -> false, != 0 -> true
CC>А началось всё с выделенного вверху.
В чистом C нет встроенного типа бул, как там было с константами типа true / false? Честно говоря я не помню...
Здравствуйте, vpchelko, Вы писали:
V>В чистом C нет встроенного типа бул, как там было с константами типа true / false? Честно говоря я не помню...
тоже нету.
Здравствуйте, vpchelko, Вы писали:
V>>>Ровняй BOOL на TRUE и FALSE. CC>>Что ты этим хотел сказать? V>НЕЛЬЗЯ СРАВНИВАТЬ ТИП BOOL с true / false.
Почему? С false можно. Без побочных эффектов.
Потому бранчстартер (mike_rs) и писал что лучше уж сравнивать с false чем с true.
Это заморочка в стиле if (5 == i), когда написание константы перед оператором == некоторым помогало от потенциальной опечатки, когда вместо сравнения получалось присваивание.
_>>>у меня еще с чистого C неприятие прямого сравнения с true. != false или в данном случае вообще if (x) гораздо лучше.
I>>Чем же сравнение с false лучше сравнения с true?
CC>Тем, что только ноль == false. А за true принимается любое ненулевое значение.
А сравнение GetSomething () == GetCorrectAnswer () какое отношение к этому имеет?
_>>>>у меня еще с чистого C неприятие прямого сравнения с true. != false или в данном случае вообще if (x) гораздо лучше.
I>>>Чем же сравнение с false лучше сравнения с true?
CC>>Тем, что только ноль == false. А за true принимается любое ненулевое значение.
I>А сравнение GetSomething () == GetCorrectAnswer () какое отношение к этому имеет?
тем, что для false оно ОК, а для true уже не факт
Здравствуйте, CreatorCray, Вы писали:
CC>тем, что для false оно ОК, а для true уже не факт
У человека было "неприятие прямого сравнения с true" вместо которого по его мнению лучше использовать "!= false". То есть он предлагает заменять сравнение на равенство с true на сравнение не неравенство с false. Ты с его мнением согласен?
Здравствуйте, igna, Вы писали:
I>Здравствуйте, CreatorCray, Вы писали:
CC>>тем, что для false оно ОК, а для true уже не факт
I>По-твоему, выражение TRUE == true может оказаться ложным?
На чистом C может, зависит от того как юзер определить true.
Здравствуйте, vpchelko, Вы писали:
I>>По-твоему, выражение TRUE == true может оказаться ложным?
V>На чистом C может, зависит от того как юзер определить true.
Здравствуйте, igna, Вы писали:
I>У человека было "неприятие прямого сравнения с true" вместо которого по его мнению лучше использовать "!= false". То есть он предлагает заменять сравнение на равенство с true на сравнение не неравенство с false. Ты с его мнением согласен?
скорее уж я согласен с его "в данном случае вообще if (x) гораздо лучше."
А про предпочтение использовать false в операциях сравнения вместо true — во времёна С это имело под собой реальные основания, которые я вероятно не смог внятно разъяснить, раз уж ветка так разрослась.
Здравствуйте, igna, Вы писали:
CC>>тем, что для false оно ОК, а для true уже не факт I>По-твоему, выражение TRUE == true может оказаться ложным?
Разумеется.
TRUE — int
true — bool
во время сравнения bool приведётся к int, т.е. будет if (TRUE == 1)
касательно числового значения TRUE у нас нет никаких гарантий кроме одной: TRUE != 0
I>Наоборот, int приведётся к bool, а именно любое ненулевое число приведется к true, и следовательно TRUE == true всегда истинно.
Пожалуй, не соглашусь. Вроде bool должен сконвертроваться в int.
#include <iostream>
int main(int argc, char** argv)
{
int x = 4;
bool flag = true;
bool result = (flag == x);
std::cout << "Result = " << result << std::endl;
return 0;
}
Данная программа выводит
Result = 0
3.9.1 Fundamental types
...
6. Values of type bool are either true or false.42) [Note: there are no signed, unsigned, short, or
long bool types or values. ] As described below, bool values behave as integral types. Values of type
bool participate in integral promotions (4.5).
Здравствуйте, Pzz, Вы писали:
Pzz>Здравствуйте, vpchelko, Вы писали:
V>>В чистом C нет встроенного типа бул, как там было с константами типа true / false? Честно говоря я не помню...
Pzz>Есть, в C99
Здравствуйте, vpchelko, Вы писали:
V>>>В чистом C нет встроенного типа бул, как там было с константами типа true / false? Честно говоря я не помню...
Pzz>>Есть, в C99
V>С99 == чистый С?
Здравствуйте, Pzz, Вы писали:
Pzz>Здравствуйте, vpchelko, Вы писали:
V>>>>В чистом C нет встроенного типа бул, как там было с константами типа true / false? Честно говоря я не помню...
Pzz>>>Есть, в C99
V>>С99 == чистый С?
Pzz>А вы как считаете?
По выше указному мнению некоего аватара, было несогласие. Лично я с "чистым" си кодом, дела ни когда не имел, в основном смешанный с/с++ код.