When I was reading the code in Google Protocol Buffers, I found confused code as follows.
1 < 2 ? (void)0 : cout << "hi" << endl;
The point is that the string "hi' will pipe through NULL by the left shift operator. As a result, nothing happened. That means this is correct code grammatically.
And I tried out little bit different code as below.
(void)0 << "hi" << endl;
Of course, It didn't work.
Lastly, I tried out this code.
string tmp;
cin >> (1 < 2 ? 0 : tmp);
It was compiled but crashed in runtime. (It works if the sign is changed inversely but the input is not stored in tmp.)
Is there someone who can walk me though what to happen in the first case? (in terms of compiler or low level if possible)
You're misreading it, 1 < 2 ? (void)0 : cout << "hi" << endl; translates to :
if(1 < 2) {
(void)0; //do nothing
} else {
cout << "hi" << endl;
}
condition ? true-state : false-state; is called a ternary operator, it absolutely has nothing to do with <<.
<< has higher precedence than ?:, so:
1 < 2 ? (void)0 : cout << "hi" << endl;
is actually equivalent to:
(1 < 2) ? (void)0 : (cout << "hi" << endl);
not to:
((1 < 2 ? (void)0 : cout)) << "hi" << endl;
(And, of course condition ? then_expression : else_expresion won't evaluate else_expression at all if condition is true.)
1 < 2 ? (void)0 : cout << "hi" << endl;
The other answers have pointed out that the operator precedence gives this a different meaning from what you assumed, so the above is equivalent to:
(1 < 2)
? (void)0
: (cout << "hi" << endl);
But it's still illegal.
If the second or third operand of the ?: conditional operator is of type void, then the other must also be of type void or must be a throw-expression.
Casting the third operand to void would address that:
1 < 2 ? (void)0 : (void)(cout << "hi" << endl);
If you can update your question to show the exact code you're asking about, we can probably explain it better.
It would also be interesting to see the context in which this appears. By itself, it would be much more legible as an if statement.
Related
By trying, I came to know that it is necessary to put parentheses around a conditional operator in a cout statement. Here a small example:
#include <iostream>
int main() {
int a = 5;
float b = (a!=0) ? 42.0f : -42.0f;
// works fine
std::cout << b << std::endl;
// works also fine
std::cout << ( (a != 0) ? 42.0f : -42.0f ) << std::endl;
// does not work fine
std::cout << (a != 0) ? 42.0f : -42.0f;
return 0;
}
The output is:
42
42
1
Why are these parentheses necessary? The resulting type of the conditional operator is known in both cases, isn't it?
The ?: operator has lower precedence than the << operator i.e., the compiler interprets your last statement as:
(std::cout << (a != 0)) ? 42.0f : -42.0f;
Which will first stream the boolean value of (a!=0) to cout. Then the result of that expression (i.e., a reference to cout) will be cast to an appropriate type for use in the ?: operator (namely void*: see cplusplus.com), and depending on whether that value is true (i.e., whether cout has no error flags set), it will grab either the value 42 or the value -42. Finally, it will throw that value away (since nothing uses it).
Because << has higher precedence than ?.
Fun exercise:
float ftest = std::cout << (a != 0) ? 42.0f : -42.0f;
Take that, Coding Horror!!!
Your code is equivalent to:
if ( std::cout << (a != 0) )
42.0f;
else
-42.0f;
It outputs 1 because, well, (a != 0) == true;
By the way, this can also work:
a != 0 ? std::cout << 42.0f : std::cout << -42.0f;
In my opinion it is better to use this way because:
It also works in the case, where we want to output different data types (telling from my experience)
For example, if had to do something like this:
std::cout << (a != 0 ? 42.0f : "Not zero!");
Will generate an error because one expression is of float type and the other is of char* type, but you can write it like this :
a != 0 ? std::cout << 42.0f : cout << "Not zero!";
This works because expressions in the conditional statement must have same data type value, and std::cout returns the same data type no matter what it is being output through it.
(Minor reason) No parenthesis - You don't have to deal with parenthesis as << have higher precedence over ?: as stated in the above answers as well. This can save us the hassle of matching closing brackets thereby reducing probability of error.
Why does this program
int a = 8;
cout << a && true ;
cout << typeid(a && true).name();
output
8bool
Frankly, I expected "truebool" or "8int".
Is operator << of cout object involved in this or is it a precedence issue?
Does it convert true to 1 as in the case when we cout << true;?
typeid(a && true) gives us bool, though the cout << a && true; is obviously a number?
Indeed it is an operator precedence issue. << has a higher precedence than &&.
One shorthand trick you can use to interpret an integer value to bool is to double-NOT it:
cout << !!a;
This is a matter of style, which may be divisive within the C++ community. So, if you don't want to be controversial, then the following may be more acceptable:
cout << (a ? true : false);
cout << static_cast<bool>(a);
cout << (a != 0);
Personally, I think that (a && true) is somewhat ugly. But I'm sure there are some who would argue otherwise.
In the end, the compiler should be generating the same result no matter how you write it.
By trying, I came to know that it is necessary to put parentheses around a conditional operator in a cout statement. Here a small example:
#include <iostream>
int main() {
int a = 5;
float b = (a!=0) ? 42.0f : -42.0f;
// works fine
std::cout << b << std::endl;
// works also fine
std::cout << ( (a != 0) ? 42.0f : -42.0f ) << std::endl;
// does not work fine
std::cout << (a != 0) ? 42.0f : -42.0f;
return 0;
}
The output is:
42
42
1
Why are these parentheses necessary? The resulting type of the conditional operator is known in both cases, isn't it?
The ?: operator has lower precedence than the << operator i.e., the compiler interprets your last statement as:
(std::cout << (a != 0)) ? 42.0f : -42.0f;
Which will first stream the boolean value of (a!=0) to cout. Then the result of that expression (i.e., a reference to cout) will be cast to an appropriate type for use in the ?: operator (namely void*: see cplusplus.com), and depending on whether that value is true (i.e., whether cout has no error flags set), it will grab either the value 42 or the value -42. Finally, it will throw that value away (since nothing uses it).
Because << has higher precedence than ?.
Fun exercise:
float ftest = std::cout << (a != 0) ? 42.0f : -42.0f;
Take that, Coding Horror!!!
Your code is equivalent to:
if ( std::cout << (a != 0) )
42.0f;
else
-42.0f;
It outputs 1 because, well, (a != 0) == true;
By the way, this can also work:
a != 0 ? std::cout << 42.0f : std::cout << -42.0f;
In my opinion it is better to use this way because:
It also works in the case, where we want to output different data types (telling from my experience)
For example, if had to do something like this:
std::cout << (a != 0 ? 42.0f : "Not zero!");
Will generate an error because one expression is of float type and the other is of char* type, but you can write it like this :
a != 0 ? std::cout << 42.0f : cout << "Not zero!";
This works because expressions in the conditional statement must have same data type value, and std::cout returns the same data type no matter what it is being output through it.
(Minor reason) No parenthesis - You don't have to deal with parenthesis as << have higher precedence over ?: as stated in the above answers as well. This can save us the hassle of matching closing brackets thereby reducing probability of error.
A line in my c++ code reads:
cout<<(i%3==0 ? "Hello\n" : i) ;//where `i` is an integer.
But I get this error:
operands to ?: have different types 'const char*' and 'int
How can I modify the code (with minimum characters)?
Ugly:
i%3==0 ? cout<< "Hello\n" : cout<<i;
Nice:
if ( i%3 == 0 )
cout << "Hello\n";
else
cout << i;
Your version doesn't work because the result types of the expressions on each side of : need to be compatible.
You can't use the conditional operator if the two alternatives have incompatible types. The clearest thing is to use if:
if (i%3 == 0)
cout << "Hello\n";
else
cout << i;
although in this case you could convert the number to a string:
cout << (i%3 == 0 ? "Hello\n" : std::to_string(i));
In general, you should try to maximise clarity rather than minimise characters; you'll thank yourself when you have to read the code in the future.
operator<< is overloaded, and the two execution paths don't use the same overload. Therefore, you can't have << outside the conditional.
What you want is
if (i%3 == 0) cout << "Hello\n"; else cout << i;
This can be made a bit shorter by reversing the condition:
if (i%3) cout << i; else cout << "Hello\n";
And a few more characters saved by using the ternary:
(i%3)?(cout<<i):(cout<<"Hello\n");
std::cout << i % 3 == 0 ? "Hello" : std::to_string(i);
But, as all the other answers have said, you probably shouldn't do this, because it quickly turns into spaghetti code.
By trying, I came to know that it is necessary to put parentheses around a conditional operator in a cout statement. Here a small example:
#include <iostream>
int main() {
int a = 5;
float b = (a!=0) ? 42.0f : -42.0f;
// works fine
std::cout << b << std::endl;
// works also fine
std::cout << ( (a != 0) ? 42.0f : -42.0f ) << std::endl;
// does not work fine
std::cout << (a != 0) ? 42.0f : -42.0f;
return 0;
}
The output is:
42
42
1
Why are these parentheses necessary? The resulting type of the conditional operator is known in both cases, isn't it?
The ?: operator has lower precedence than the << operator i.e., the compiler interprets your last statement as:
(std::cout << (a != 0)) ? 42.0f : -42.0f;
Which will first stream the boolean value of (a!=0) to cout. Then the result of that expression (i.e., a reference to cout) will be cast to an appropriate type for use in the ?: operator (namely void*: see cplusplus.com), and depending on whether that value is true (i.e., whether cout has no error flags set), it will grab either the value 42 or the value -42. Finally, it will throw that value away (since nothing uses it).
Because << has higher precedence than ?.
Fun exercise:
float ftest = std::cout << (a != 0) ? 42.0f : -42.0f;
Take that, Coding Horror!!!
Your code is equivalent to:
if ( std::cout << (a != 0) )
42.0f;
else
-42.0f;
It outputs 1 because, well, (a != 0) == true;
By the way, this can also work:
a != 0 ? std::cout << 42.0f : std::cout << -42.0f;
In my opinion it is better to use this way because:
It also works in the case, where we want to output different data types (telling from my experience)
For example, if had to do something like this:
std::cout << (a != 0 ? 42.0f : "Not zero!");
Will generate an error because one expression is of float type and the other is of char* type, but you can write it like this :
a != 0 ? std::cout << 42.0f : cout << "Not zero!";
This works because expressions in the conditional statement must have same data type value, and std::cout returns the same data type no matter what it is being output through it.
(Minor reason) No parenthesis - You don't have to deal with parenthesis as << have higher precedence over ?: as stated in the above answers as well. This can save us the hassle of matching closing brackets thereby reducing probability of error.