Почему в условном операторе (?:) второй и третий операнды должны иметь один и тот же тип?
Почему в условном операторе (?:
) второй и третий операнды должны иметь один и тот же тип?
Мой код:
#include <iostream>
using std::cout;
int main()
{
int a=2, b=3;
cout << ( a>b ? "a is greater\n" : b ); /* expression ONE */
a>b? "a is greater\n" : b; /* expression TWO */
return 0;
}
При компиляции с помощью g++ возникает ошибка:
main.cpp:7:36: error: operands to ?: have different types ‘const char*’ and ‘int’
main.cpp:8:28: error: operands to ?: have different types ‘const char*’ and ‘int’
Я блуждаю, почему они должны иметь один и тот же тип?
(1) На мой взгляд, если (a>b)
истинно, тогда выражение ( a>b ? "a is greater\n" : b )
вернется "a is greater\n"
, а cout << "a is greater\n"
выведет эту строку;
иначе выражение вернет b
, а cout << b
выведет значение b.
Но, к сожалению, это не так. Почему?
(2) Второе выражение получает ту же ошибку.
PS: Я знаю, это стандарт, который говорит, что это должно быть так, но почему стандарт так говорит?
Ответы
Ответ 1
Вы должны попытаться разложить то, что происходит, чтобы понять:
cout << ( a>b ? "a is greater\n" : b );
Это означает:
operator<<(cout, ( a>b ? "a is greater\n" : b ));
На этом этапе компилятор должен выбрать одну из следующих перегрузок:
ostream& operator<<(ostream&, int);
ostream& operator<<(ostream&, const char*);
Но это невозможно, потому что тип результата тернарного оператора пока неизвестен (только во время выполнения).
Чтобы все было понятнее:
auto c = a>b ? "test" : 0;
Каким будет тип c
? Это невозможно решить во время компиляции. С++ - это статически типизированный язык. Все типы должны быть известны во время компиляции.
EDIT:
Вы думаете о a ? b : c
следующим образом:
if (a)
b;
else
c;
Пока это на самом деле:
if (a)
return b;
else
return c;
Ответ 2
Я блуждаю, почему они должны иметь один и тот же тип?
В С++ любое выражение должно иметь один тип, и компилятор должен иметь возможность выводить его во время компиляции.
Это связано с тем, что С++ - это статически типизированный язык, в котором все типы должны быть известны во время компиляции.
Ответ 3
Они не обязательно должны быть одного типа. Например, выражение типа: int a = argc > 1 ? 2 : 'a';
вполне допустимо, хотя 2
имеет тип int
, а 'a'
имеет тип char
.
Однако должно быть неявное преобразование в один и тот же тип. Причина проста: оператор должен дать одно значение, и компилятор должен уметь определять тип этого значения. Если нет никакого неявного преобразования между этими двумя типами, для выражения не существует ни одного типа.
Ответ 4
Это сильный язык типа, и ему нужно обрабатывать целое?: как переменная или оператор, например:
int i = 3;
int j = 5;
int k = (2 > 1 ? i : j) + 3;
в таком случае, что бы вы ожидали, что он должен сделать для вас, если я - строка?
Ответ 5
выражение ?:
будет выдавать значение (называемое rvalue), которое должно быть присвоено переменной (которая называется lvalue), как J.N. metioned, С++ - статически типизированный язык, lvalue должен быть известен во время компиляции.
int num = a>b ? a : "eh, string?";
Приведенный выше код не будет компилироваться, поэтому переменная num
может содержать только int, строка не разрешена.