C++ arithmetic if operator - c++

I've been trying to get the arithmetic if operator to work but I just can't seem to do it.
I'm new to C++ and still learning the basics but I'm just wondering if I'm using this operator correctly. It's supposed to return false if x < y. Is this the correct way to do it? I'm aware I can use an if else but I'm just wondering if I can also do it like this and if I can what I'm doing wrong.
#include <iostream>
using namespace std;
int x =0;
int y =1;
bool test()
{
return (x < y) ? true : false;
}
int main()
{
cout << test;
return 0;
}

Change
cout << test;
to
cout << test();
Otherwise you're not calling the function.
Also, the following:
return (x < y) ? true : false;
does the opposite of what you say you're trying to do ("return false if x < y").
The correct way is:
return (x < y) ? false : true;
Note that in this case the ternary operator is unnecessary, since you can simply do:
return !(x < y);

You state:
It suppose to return false if x < y
And you're trying to learn about the arithmetic if (ternary) operator, so ignore all the advice to eliminate it.
The first part after the ? is what will be returned if the expression is true, and the second part after the : is what will be returned if it is not true. Thus you have your return values reversed, and it should be:
return (x < y) ? false : true;

Or even more simply,
return (x >= y);

Related

Why operator< of c++ map do not work with <=

I have this following program for map with custom keys:
class MyClass
{
public:
MyClass(int i): val(i) {}
bool operator< (const MyClass& that) const { return val <= that.val; }
private:
int val;
};
int main()
{
MyClass c1(1);
MyClass c2(2);
MyClass c3(3);
map<MyClass, int> table;
table[c1] = 12;
table[c2] = 22;
table[c3] = 33;
cout << "Mapped values are: " << table.lower_bound(c1)->second << " " << table[c2] << " " << table[c3] << endl;
}
The output comes as:
Mapped values are: 22 0 0
But if I compare using < or > in the operator< instead of <= then everything works fine. And the output comes as:
Mapped values are: 12 22 33
Can someone explain why <= does not work at all, but < and even > works?
The comparison function used by std::map must implement a strict weak ordering. That means it must implement the following rules given objects x, y, and z:
op(x, x) must always be false
if op(x, y) is true then op(y, x) must be false
if op(x, y) && op(y, z) is true then op(x, z) must also be true
if !op(x, y) && !op(y, x) is true then !op(x, z) && !op(z, x) must also be true
The <= operator does not satisfy these conditions because, given x = y = 1, x <= x is not false and both x <= y and y <= x are true.
std::map uses these rules to implement its comparisons. For example, it could implement an equality check as !(op(x, y) || op(y, x)). Given x = 4, y = 4, and op = operator<= this becomes !(4 <= 4 || 4 <= 4), so 4 does not compare equal to 4 because the first rule above was broken.
On cppreference we find this quote.
Everywhere the standard library uses the Compare concept, uniqueness is determined by using the equivalence relation. In imprecise terms, two objects a and b are considered equivalent (not unique) if neither compares less than the other: !comp(a, b) && !comp(b, a).
This means that with you current compare
bool operator< (const MyClass& that) const { return val <= that.val; }
if you have two MyClass with val 5 and 5, 5 <= 5 will return true, and they will not be considered equivalent.

Why this code produce 1?

Why this code produce 1? Someone, describe it for me pls.
#include <iostream>
using namespace std;
int main(){
int x = 0;
int y = 0;
if (x++&&y++){
y += 2;
}
cout << x + y << endl;
return 0;
}
Initially x and y are 0
Therefore x++ evaluates to false, and the second operand of && is never evaluated. x++ does increment x to 1. Since the condition is false, the conditional branch is not entered.
x + y is 1 + 0 which equals 1
user2079303 explains nicely (+1 by me already), as extension, I'll go a little more into detail:
if(x++) evaluates the value of x before the incrementation, so this little piece of code is equivalent to the following (need to buffer the old value!):
int tmp = x;
x++;
if(tmp)
Be aware that within c && cc, the second condition cc is not evaluated any more if c is already false! So if(x && y) is equivalent to
if(x)
{
if(y)
{
// ...
}
}
Putting all this together, your code is equivalent to this variant, where I separated the if clause into code lines each one containing only one single instruction:
int x = 0;
int y = 0;
int tmp = x;
x++;
if(tmp)
{
tmp = y;
y++;
if(tmp)
y += 2;
}
Suppose, your output now is quite obvious...

Return statement in conditional operator

I have a code segment as follows:
if(a < b)
{
x = y;
return w;
}
/* all unrelated variables above*/
x = something;
y = something;
/*both x and y from above*/
x and y are global variables, and they are modified inside the if part, I need to assign y to x and then return w, or simply a constant.
I need to use a ternary operator to replace the if part:
I tried the following:
return (((a < b) ? (x = y, w) : 1), (x = something, y = something));
But, I don't seem to get the desired result. I know it is wrong. This is because I used the return stement from a similar expression, that is:
if(x < y)
return (x = y);
return 1;
Which I wrote as:
return ((x < y) ? x = y : 1);
But, how do I return a value, that involves a prior assignment of a completely different variable in a ternary operator?
The solution suggested by Mankarse:
return (a < b) ? (x = y, w) : (x = something, y = something, z);
Is actually equivalent to:
if (a < b) {
x = y;
return w;
}
/* all unrelated variables above*/
x = something;
y = something;
return z;
The second return statement is important.
You cannot conditionally return from the middle of an expression, because return is a statement, you have to return the whole expression. So it really depends on how you want to proceed after the assignment to the y. Or if you really need to change the order of execution in the middle of an expression, you can throw an exception, but that, I guess, would be too complicated in this case.
Put the code block inside a function.
function f(){
x = y;//assumes x, y and w are global.
return w;
}
Then use the function in the conditional statement.
(a < b) ? f() : "value to return if a>=b";
You don't need to put return before a conditional statement since automatically returns 1 of the value, depends on the evaluation of the condition.

how to compare structs

I am having difficulties to set up the comparison correctly.
Here is an example of my problem, where my code wrongly assumes {1,2}={2,1}: http://ideone.com/i7huL
#include <iostream>
#include <map>
using namespace std;
struct myStruct {
int a;
int b;
bool operator<(const myStruct& rhs) const {
return rhs.a < this->a && rhs.b < this->b;
}
};
int main() {
std::map <myStruct, int> mymap ;
myStruct m1={1,2};
myStruct m2={2,1};
mymap.insert(make_pair(m1,3));
std::map<myStruct, int>::iterator it1 = mymap.find(m1);
std::map<myStruct, int>::iterator it2 = mymap.find(m2);
cout << it1->second << it2->second;
// here it1->second=it2->second=3, although I would have expected it2 to be equal to map.end().
}
I could use || instead of &&, but I'm not sure this is the correct way either. I just want to have operator< implemented in such a way that I am able to find objects in my map, without making any errors, as is the case in the code I linked to.
Thanks.
Yes, this operator implementation doesn't make much sense. I'd recommend:
bool operator<(const myStruct& rhs) const {
return rhs.a < this->a || (rhs.a == this->a && rhs.b < this->b);
}
bool operator<(const myStruct& rhs) const {
if (a < rhs.a) return true;
if (a == rhs.a) return b < rhs.b;
return false;
}
If you are looking for a generalization to many data members, there is a great example using C++11 std::tie:
struct S {
int n;
std::string s;
float d;
bool operator<(const S& rhs) const {
return std::tie(n, s, d) < std::tie(rhs.n, rhs.s, rhs.d);
}
};
The problem is that your operator does not define a strict weak ordering. Think through your how your example of {1,2} and {2,1} would go down in your operator. Assume X = {1,2}, and Y = {2,1}.
Is X < Y? Is 1 < 2 AND 2 < 1? No, therefore X is not less than Y.
Is Y < X? Is 2 < 1 AND 1 < 2? No, therefore Y is not less than X.
So, if X is not less than Y, and Y is not less than X, what's left? They're equal.
You need to pick one of the members of your struct, either a or b to be the primary comparison. If the primary comparison results in equality, only then do you check the secondary comparison. Just like when you alphabetize something. First you check the first letter, and only if they are equal do you go on to the next. Hans Passant has provided an example of this.
Here's a more serious problem example for your operator. The one I gave above is not necessarily bad, because maybe you want {1,2} to be considered equal to {2,1}. The fundamental problem crops with a set of values like this: consider X = {1,1}, Y = {1,2}, Z = {2,2}
With your operator, X is definitively less than Z, because 1 is less than 2. But X comes out equal to Y, and Y comes out equal to Z. In order to adhere to strict weak ordering, if X = Y, and Y = Z, then X should equal Z. But here that is not the case.
You asked about generalising to four int members, here's how I would structure such code for maximum clarity.
bool operator<(const myStruct& rhs) const
{
if (a < rhs.a)
return true;
if (a > rhs.a)
return false;
if (b < rhs.b)
return true;
if (b > rhs.b)
return false;
if (c < rhs.c)
return true;
if (c > rhs.c)
return false;
if (d < rhs.d)
return true;
if (d > rhs.d)
return false;
return false;
}
You can easily extend such code for as many data members as you wish.
The simplest solution uses std::tie to compare the tuples.
return std::tie(rhs.a, rhs.b) < std::tie(a, b);
This generalizes very quickly and simply to more data members.
I prefer to write this by comparing elements for equality until two are found that are different:
bool operator<(const myStruct& rhs) const {
if (a != rhs.a)
return a < rhs.a;
if (b != rhs.b)
return b < rhs.b;
return false; // this and rhs are equal.
}
I find this clearer and more extensible than writing a single expression with a mix of || and && (as per #HansPassant), and more compact than #jahhaj's approach of having each passing test lead to a return true; or return false;. Performance is about the same, unless you know something about the distribution of values. There is an argument for avoiding operator==() and just using operator<(), but that only applies if you are trying to write maximally generic template code.
Problem is that you need to know what your structure represents. Otherwise defining a < operator would just become arbitrary. Others won't be able to give you a fitting answer. Take an example where when your structure represents a cartisian coordinate of a point in 2D. In this case you could define a meaningful ordering operator such as the distance from the origin for the structure.
i.e, distance d1 = this->a*this->a + this->b*this->b
distance d2 = rhs.a*rhs.a + rhs.b*rhs.b
if(d1 < d2)
return true;
else
return false;

C++ Visual Studio Express - Assigning return value fails function

I'm having a very odd problem with my program and am hoping you can help. I have a really basic pair of functions. One calls the other and requires a return int.
For reasons completely unknown reasons the first function fails to print out match even though the conditions are true if the return value to a variable is assigned to a variable ie:
Function 1:
int function1(int posX, int posY){
int x=1;
int y=1;
if (posX == X && posY == Y){
printf("Match");
return 1;
}
}
Function 2:
int i = function1(1, 1);
Does work:
function1(1,1);
So to clarify, I'm saying that its working if I get the message "Match".
(posX == X && posY == Y)
C/C++ is case-sensitive. What do "X" and "Y" stand for?
Maybe try changing them to lowercase?
Also, always try to return a value even if there is NOT a match (the function function1 is supposed to be returning an int value, right?)
Code : (corrected)
int function1(int posX, int posY){
int x=1;
int y=1;
if ((posX == x) && (posY == y)){
printf("Match");
return 1;
}
return 0;
}