I wrote this program:
#include <iostream>
using namespace std;
void unequalityOperator(){
cout << "Running unequalityOperator..." << endl;
bool a = true, b = false;
if ( a != b ) cout << "!=" << endl;
if ( a =! b ) cout << "=!" << endl;
}
int main()
{
unequalityOperator();
system("pause");
return 0;
}
And I was surprised that it run and printed both of the strings. So I tried the same thing with some other binary operators like <=, >=, etc. but it didn't work.
Therefore I would like to understand whether there is a difference between != and =!.
I do know that there are some operators like +=, -=, etc. that work differently and, e.g., the difference between += and =+ is that the addition will occur before or after (respectively) the actual command. And for this reason I suspect that there is difference with the hierarchy in the implementation of these operators, but I am not really sure what.
So please help me understand.
The expression a = !b is an assignment of the value !b into the variable a.
The evaluation of this expression within an if statement is the new value of a.
Since b is set to false and you are assigning !b into a, this value is true.
In first case the != operator is a single inequality operator. In second case it is an assignment operator = with logical not operator !. So in the second case you are assigning not b to a and returning it's result true
This might help to clear things up:
!= : not-equal operator
=! : these are really two operators: assignment operator and unary logical NOT operator
+= : sum-assignment operator
=+ : these are really two operators: assignment operator and unary + operator
-= : difference-assignment operator
=- : these are really two operators: assignment operator and unary - operator
Also, as these were in your question before being edited out:
++= : two operators: postfix increment operator and assignment operator
=++ : two operators: assignment operator and prefix increment operator
I hope you notice the pattern.
For reference:
http://en.cppreference.com/w/cpp/language/operator_precedence
http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
Related
Why this doesn't work on C but works on C++?
(0) ? a = 1 : a = 2;
The languages have differences in operator precedence.
In C++, the ternary operator has the same precedence as assignment operators, with the note
The expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized: its precedence relative to ?: is ignored.
In C, the ternary operator has higher precedence than assignment. It also has a the same note about the middle expression.
What this means is that in C, the expression is parsed as if it were parenthesized:
((0) ? (a = 1) : a) = 2;
which is invalid because the conditional expression doesn't return an L-value.
In dart we have plenty of ternary operators.
But do we have one ternary operator just for if condition?
Example
In condition
if (num == 1){
print(true);
} else {
print(false);
}
In ternary
print(num == 1 ? true : false);
So do we have any ternary operator just for true condition like above example?
if (num == 1) {
print(true);
}
No.
The conditional operator ?/: in Dart requires all three operands.
It does so because all expressions must have a value, and if you could do just e1 ? e2, then the expression has no value if e1 is false.
It's not impossible to conceive of a binary conditional operator where the missing expression defaults to null, say (e1?:elseExpression) or (e1?thenExpression:), but then you can also just write the null, and saving four letters is probably not worth the potential loss of readability.
Ob-nitpick. The conditional operator in Dart is one of two ternary operators (operators requiring three operands, like binary operators require two operands), the other ternary operator being []=.
I wonder, since && is short-circuiting, we can use:
b && f(args) to replace if(b){ f(args);}
Where if b is true, function f will be executed. The drawback is that f must return a bool. A true() wrapper function could be used.
I know () has higher precedence than <<, and << has higher precedence than ==, but I want to know why I can't write cout<<a==b; yet can write cout<<(a==b); in C++.
How the compiler translates cout<<a==b; and then shows error?
<< has higher precedence than ==
as you can see here.
The statement
cout<<a==b
is equivalent to
(cout<<a)==b
The expression
cout<<a
returns a stream. This stream is compared to b. If there is no left shift operator for a stream and a or no comparing operator for a stream and b this causes a compiler error
cout<<a==b is similar to (cout<<a) == b as << has higher precedence over ==. Now cout<<a will be syntactically incorrect if the type of a is not supported for <<. Next, if a has an overload for the << operator, it will again be syntactically wrong as the == operator can't operate with std::stream and type of b unless b overloads this compare operator.
But in case of cout<<(a==b), a==b will result in a boolean value. As the << operator support boolean value it is a valid operation.
<< priority is higher than == so it's interpreted as (cout<<a)==b
but = has lower so you can do :
bool t = a == b
This question already has answers here:
Conditional operator used in cout statement
(3 answers)
Closed 3 years ago.
I was solving a problem about movement of a bishop on a chessboard. At one point of my code, I had the following statement:
std::cout << (abs(c2-c1) == abs(r2-r1)) ? 1 : 2 << std::endl;
This generates the following error:
error: invalid operands of types 'int' and '<unresolved overloaded function type>' to binary 'operator<<'
However, I instantaneously fixed this error by including an additional variable in my code:
int steps = (abs(c2-c1) == abs(r2-r1)) ? 1 : 2;
std::cout << steps << std::endl;
How does the ternary operator work, and how is its return type determined (as the compiler called it <unresolved overloaded function type>)?
This has nothing to do with how the return type is deduced and everything to do with operator precedence. When you have
std::cout << (abs(c2-c1) == abs(r2-r1)) ? 1 : 2 << std::endl;
it isn't
std::cout << ((abs(c2-c1) == abs(r2-r1)) ? 1 : 2) << std::endl;
because ?: has lower precedence than <<. That means what you actually have is
(std::cout << (abs(c2-c1) == abs(r2-r1))) ? 1 : (2 << std::endl);
and this is why you get an error about an <unresolved overloaded function type>. Just use parentheses like
std::cout << ((abs(c2-c1) == abs(r2-r1)) ? 1 : 2) << std::endl;
and you'll be okay.
You have to put parentheses around a ternary operation:
std::cout << ((abs(c2-c1) == abs(r2-r1)) ? 1 : 2) << std::endl;
If not the the << operator goes to the 2 and it gives an error because it doesn't have such overloaded function.
This happens because the bitwise left shift operator (<<) has a higher precedence than the ternary operator. You can see the full list of operators and their precedence in this page of the C++ reference.
Due to operator precedence, that line is treated as:
(std::cout << (abs(c2-c1) == abs(r2-r1))) ? 1 : (2 << std::endl);
Change it to
std::cout << ((abs(c2-c1) == abs(r2-r1)) ? 1 : 2) << std::endl;
// ^----------------------------------^
// Surrounding parentheses
It's easy to see the mistake when the parsing order is visualized:
std::cout << (abs(c2-c1) == abs(r2-r1)) ? 1 : 2 << std::endl;
\_______/ <--- #1
\________________________/ V \~~~~error~~~/ <--- #2
\_____________________________________________/ <--- #3
\__________________________________________________________/ <--- #4
\___________________________________________________________/ <--- #5
The literal answer to the question you asked is the algorithm in the [expr.cond] secton of the C++ language standard.
The basic rule “determined whether an implicit conversion sequence can be formed from the second operand to the target type determined for the third operand, and vice versa.” If there isn’t one possible conversion, or there is more than one, it’s a syntax error, but there are several special cases (which don’t apply here):
If both are arithmetic or enum types, you get the same kind of implicit conversion for p ? a : b that determines the type of an expression such as a + b or a * b.
One of the targets may be a throw expression, and is treated as having the type of the other.
If one of the targets is a bitfield, so is the type of the conditional expression
Pointers with different qualifiers (such as const and volatile) have their qualifiers unified.
The result is a glvalue if the targets are glvalues of the same type, and a prvalue otherwise.
When in doubt, you can always explicitly cast one or both of the operands so that they have the same type.
Your actual problem here is operator precedence, as the accepted answer explains. That is, the compiler parses the third operand as 2 << std::endl, rather than 2.
According to cppreference:
When parsing an expression, an operator which is listed on some row of the table above with a precedence will be bound tighter (as if by parentheses) to its arguments than any operator that is listed on a row further below it with a lower precedence. For example, the expressions std::cout << a & b and *p++ are parsed as (std::cout << a) & b and *(p++), and not as std::cout << (a & b) or (*p)++.
Operators that have the same precedence are bound to their arguments in the direction of their associativity. For example, the expression a = b = c is parsed as a = (b = c), and not as (a = b) = c because of right-to-left associativity of assignment, but a + b - c is parsed (a + b) - c and not a + (b - c) because of left-to-right associativity of addition and subtraction.
Associativity specification is redundant for unary operators and is only shown for completeness: unary prefix operators always associate right-to-left (delete ++*p is delete (++(*p))) and unary postfix operators always associate left-to-right (a[1][2]++ is ((a[1])[2])++). Note that the associativity is meaningful for member access operators, even though they are grouped with unary postfix operators: a.b++ is parsed (a.b)++ and not a.(b++).
Operator precedence is unaffected by operator overloading. For example, std::cout << a ? b : c; parses as (std::cout << a) ? b : c; because the precedence of arithmetic left shift is higher than the conditional operator.
Why can I overload and use ++ operator in LHS and RHS while + one works just in LHS mode?
class B {
public:
string operator ++ () { return "hello"; }
string operator + () { return "hello2"; }
};
int main ()
{
B b;
string s = +b ;
s = b+ ; // compile error syntax error : ';'
s = b++;
s = ++b;
return 0;
}
Overloaded operators can only be used with the same syntax as the corresponding built-in ones. The built-in ++ is defined as either a prefix or postfix operator; the built-in + is only defined as a prefix operator (and of course as a binary operator).
Note that your code won't compile even without the b+ line, since you're missing a postfix version of ++:
string operator ++ (int) { return "postfix"; }
Why I can overload and use ++ operator in LHS and RHS
Your code actually produces two errors:
main.cpp:16:12: error: expected expression
s = b+ ; // compile error syntax error : ';'
^
main.cpp:18:10: error: cannot increment value of type 'B'
s = b++;
~^
So you actually haven't overloaded the post-increment operator, only the pre-increment operator. Your question remains, however, since you could overload post-increment if you wanted to but C++ does not offer any similar syntax for overloading a postfix unary plus operator.
C++ does not change the way operators in expressions are parsed based on operator overloads. It will only allow you to overload operators that already exist, and those operators will be parsed exactly as if operator overloads do not exist. It's only after parsing that C++ will then look around for operator overloads to figure out what the parsed expression means. Thus C++ offers a way to overload a post-increment operator because it already handles parsing the post-increment operator, but it does not already handle parsing a postfix plus operator.
Limiting C++ operator overloads to existing operators was done because it is simpler to implement a parser if the parser doesn't have watch out for arbitrary uses of operators. That doesn't mean it can't be done, however. The language Swift, for example, allows arbitrary operator overloading for binary, prefix unary, and postfix unary operators, including creating completely new operators.