Может ли каждая конструкция if-else быть заменена эквивалентным условным выражением?
(У меня нет серьезной потребности в этом ответе, я просто любопытен.)
может ли каждая конструкция if-else быть заменена эквивалентным условным выражением с помощью условного оператора ?:
?
8 ответов
все ли конструкции if-else могут быть заменены эквивалентным условным выражением с помощью условного оператора?
нет, вы задали этот вопрос задом наперед. "тела" if/else содержат операторы, и невозможно превратить каждое утверждение в выражение, такие как try, while, break заявления, а также объявления. Однако многие "утверждения" на самом деле являются замаскированными выражениями:
++i;
blah = 42;
some_method(a,b,c);
все это операторы, которые состоят из одного выражения (increment, assignment, function-call, соответственно) и могут быть превращены в выражения внутри условного.
Итак, давайте перевернем вопрос, так как похоже, что вы действительно хотите знать, насколько эквивалентны операторы if/else троичным условным выражениям: можно ли заменить каждое условное выражение эквивалентными операторами if/else? почти все, да. Типичным примером является возвращение заявления:
return cond ? t : f;
// becomes:
if (cond) return t;
else return f;
, но и другие выражения:
n = (cond ? t : f);
// becomes:
if (cond) n = t;
else n = f;
который начинает указывать, где условные выражения не могут быть легко заменены:инициализации. Поскольку инициализировать объект можно только один раз, необходимо разбить инициализацию, использующую условие, на явную временную переменную:
T obj (cond ? t : f);
// becomes:
SomeType temp;
if (cond) temp = t;
else temp = f;
T obj (temp);
обратите внимание, что это гораздо более утомительно / громоздко и требует чего-то зависящего от типа, если SomeType не может быть сконструированным и назначенным по умолчанию.
на поверхности, нет. Условный оператор-это выражение (То есть он имеет значение), а if/else-оператор (таким образом, не имеет значения). Они удовлетворяют различные "потребности" в синтаксисе языка.
однако, поскольку вы можете игнорировать значения выражений, и поскольку любое выражение можно превратить в оператор, добавив точку с запятой, вы можете по существу эмулировать if / else с условным выражением и двумя вспомогательными функциями:
// Original code:
if (condition) {
// block 1
}
else {
// block 2
}
// conditional expression replacement:
bool if_block() {
// block 1
return true;
}
bool else_block() {
// block 2
return true;
}
// Here's the conditional expression. bool value discarded:
condition ? if_block() : else_block();
впрочем, имея сказал Это, я не уверен, что это что-то большее, чем любопытство...
Нет, конечно, нет. По причинам, уже упомянутым, и не только!
#include <cstdlib>
#include <iostream>
int main()
{
if(int i = std::rand() % 2)
{
std::cout << i << " is odd" << std::endl;
}
else
{
std::cout << i << " is even" << std::endl;
}
}
проверьте, где объявлено is. Это не часто используемый метод, но его можно использовать в таких ситуациях, как COM, где каждый вызов возвращает HRESULT, который (почти всегда) равен нулю при успехе (S_OK), ненулевой при неудаче, поэтому вы можете написать что-то вроде:
if(HRESULT hr = myInterface->myMethod())
{
_com_raise_error(hr);
}
тернарный оператор не может сделать ничего аналогичного.
if( cond )
break;
else
a=b;
не всегда можно заменить на ?:
оператора. Вы можете часто (если не всегда) переосмысливать весь свой код, чтобы обеспечить эту замену, но, как правило, вы не можете поместить ничего, что контролирует выполнение в ?:
. break
, return
, петель, throw
, etc.
в принципе, да:
if (A) B; else C
становится
try {
A ? throw TrueResult() : throw FalseResult();
// or: throw A ? TrueResult() : FalseResult();
} catch (TrueResult) {
B;
} catch (FalseResult) {
C;
}
по сравнению с использованием процедур (которые более естественны), это позволяет break
, continue
, return
etc. Это требует оценки A
не с TrueResult
/FalseResult
но если вы используете эти исключения только для имитации if
, это не будет проблемой.
использование условного оператора приводит к выражению, и оба потенциальных результата условного оператора должны быть "совместимыми" (конвертируемыми в один и тот же тип).
An if
-else
construct не нужно даже "возвращать" какой-либо тип, тем более один и тот же из обеих ветвей.
условный оператор ожидает, что оба элемента будут следовать за ?
быть rvalues (так как результат условного оператора сам по себе является rvalue) - поэтому, хотя я не совсем эксперт по стандартам C/C++, моя интуиция будет заключаться в том, что следующее будет запрещено (или в противном случае, чрезвычайно плохой стиль кодирования...):
(condition) ? return x : return y;
в то время как версия if-else будет довольно стандартной:
if(condition) return x;
else return y;
Теперь, что сказал, не могли бы вы взять любую программу и написать аналогично функционирующую программу, которая не использовала if-else? Конечно, вы, вероятно, могли. Но это не значит, что это хорошая идея. ;)
GCC имеет statement expression
, используя его, вы можете переписать if
заявления эквивалентно ?:
выражения:
if (<expression>)
<statement1>
else
<statement2>
"правка":void
бросания служат двум целям. Подвыражения в ?:
должен иметь тот же тип, и без void
cast компилятор может печатать warning: statement with no effect
.
(<expression>)? (void)({<statement1>}) : (void)({<statement2>});