Why in conditional operator (?:), second and third operands must have the same type?

Yishu Fang picture Yishu Fang · Mar 12, 2012 · Viewed 8.7k times · Source

Why in conditional operator(?:), second and third operands must have the same type?

My code like this:

#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;
}

When compile it using g++, it issue an error:

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’

I wonder why they must have the same type?

(1) In my opinion, if (a>b) is true, then the expression ( a>b ? "a is greater\n" : b )will return "a is greater\n" and cout << "a is greater\n" will output that string;
otherwise the expression will return b, and cout << b will output the value of b.

But, unfortunately it is not like this. WHY?

(2) The second expression gets the same error.

PS: I know, it is the standard who says it must be like this, but, why the standard say so?

Answer

J.N. picture J.N. · Mar 12, 2012

You should try to decompose what's happening to understand:

cout << ( a>b ? "a is greater\n" : b );

This translates to :

operator<<(cout, ( a>b ? "a is greater\n" : b ));

At that stage the compiler must choose one of the following overloads:

ostream& operator<<(ostream&, int);
ostream& operator<<(ostream&, const char*);

But it can't because the type of result of the ternary operator is not known yet (only at runtime).

To make things clearer think like this:

 auto c = a>b ? "test" : 0;

What would be the type of c ? It can't be decided at compile time. C++ is a statically typed language. All types must be known at compile time.

EDIT:

You are thinking of a ? b : c in the following way:

if (a)
    b;
else
    c;

While it is actually this:

if (a)
    return b;
else
    return c;