Почему в условном операторе (? :) второй и третий операнды должны иметь одинаковый тип? - PullRequest
15 голосов
/ 12 марта 2012

Почему в условном операторе (?:) второй и третий операнды должны иметь одинаковый тип?

Мой код такой:

#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: Я знаю, это стандарт, который говорит, что так должно быть, но почему стандарт так говорит?

Ответы [ 5 ]

30 голосов
/ 12 марта 2012

Вы должны попытаться разложить то, что происходит, чтобы понять:

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?Это не может быть решено во время компиляции.C ++ является статически типизированным языком.Все типы должны быть известны во время компиляции.

РЕДАКТИРОВАТЬ:

Вы думаете о a ? b : c следующим образом:

if (a)
    b;
else
    c;

Хотя это действительно так:

if (a)
    return b;
else
    return c;
5 голосов
/ 12 марта 2012

Интересно, почему они должны быть одного типа?

В C ++ любое выражение должно иметь один тип, и компилятор должен иметь возможность вывести его во время компиляции.

Это связано с тем, что C ++ является языком статической типизации, в котором все типы должны быть известны во время компиляции.

4 голосов
/ 12 марта 2012

Они на самом деле не должны быть одного типа.Например, выражение вроде: int a = argc > 1 ? 2 : 'a'; вполне допустимо, даже если 2 имеет тип int, а 'a' имеет тип char.

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

2 голосов
/ 12 марта 2012

выражение ?: создаст значение (называемое rvalue ), которое должно быть присвоено переменной (которая называется lvalue ), как J.N. С ++ C ++ - это статически типизированный язык, lvalue должен быть известен во время компиляции.

int num = a>b ? a : "eh, string?";

Приведенный выше код не будет компилироваться, поскольку переменная num может содержать только int , строка не допускается.

2 голосов
/ 12 марта 2012

Это язык сильных типов, и его нужно рассматривать как целое ?: как переменную или выражение, например:

int i = 3;
int j = 5;
int k = (2 > 1 ? i : j) + 3;

, в таком случае, что вы ожидаете, что это должно сделать для вас, если ятакое строка?

...