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.
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.
I'm starting to learn C++, and something useful from my main language Lua, is the ability to say:
print(true/false and 1 or 0)
1 or 0 being anything but it seems in c++ it doesnt work the same way?
What I tried for C++ was
cout << (score == 0) and "Valid";
But only a true if check seems to work
if (score == 0) {
cout << "Valid";
} else {
cout << "A";
}
std::cout << ((score == 0) ? "Valid" : "A");
The << in your code isn't simply a syntax, it's an operator:
std::basic_ostream<CharT,Traits>::operator<<
Your attempt will not produce any compilation errors (assuming you have using namespace std;):
cout << (score == 0) and "Valid";
// ^^ T/F ^^ ^^ T ^^
Apply some boolean algebra and that's equivalent to:
cout << true; // if score is 0
cout << false; // if score is not 0
That's certainly not what you are trying to acheive.
Are there ways to do if statements inside a cout line?
if (score == 0)
cout << "Valid";
else
cout << "A";
You can do that using the conditional operator ?:
cout << (score == 0 ? "Valid" : "A");
But this approach is not guaranteed to work always. For example:
cout << (condition ? "String" : 1234);
Reason: Why in conditional operator (?:), second and third operands must have the same type?
Rearranging it like this will work:
condition ? cout << "String" : cout << 1234;
Now, talking about your Lua style:
print(true/false and 1 or 0)
I don't know Lua but that looks like a function. If you are looking for some template like that, try this:
template <typename T, typename U>
void conditionalPrint(const bool& condition, const T& arg1, const U& arg2)
{
condition ? cout << arg1 : cout << arg2;
}
You can use it like this:
conditionalPrint(score == 0, "Valid", "A");
conditionalPrint(someCondition, "String", 1234);
Of course, I'm not going to explain how that works because you're new to C++. I would still recommend the if-else way of doing it. Readability of your code is very important:
if (condition)
{
cout << "true block";
}
else
{
cout << "false block";
}
"Lot can be learned by comparing two lanugages and try to see if what can be done in one can also be done in the other, but usually what is idiomatic in one can be crap in the other. Anyhow, I had my fun with exploring the issue, but imho the conclusion is as important as the rest of the answer" - idclev
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.
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.