I am learning how to write the comparator in C . At first time, I return num1<num2, as a result I get a set in ascending order. Then I return num1>num2 and I get a set in descending order. Now I try to return num1-num2 which should equal to num1>num2 in my opinion, I get a set in descending order as predicted. But when I try to return num2-num1, I still get a set in descending order. How could it happen? Is there any difference between return num2-num1 and return num1<num2?
#include <iostream>
#include <set>
using namespace std;
struct myCmp{
bool operator()(const int& num1, const int& num2){
return num2-num1;
}
};
int main()
{
set<int,myCmp> st;
st.insert(1);
st.insert(2);
st.insert(3);
for(auto it=st.begin();it!=st.end();it ){
cout<<*it<<endl;
}
return 0;
}
CodePudding user response:
I try to return
num1-num2which should equal tonum1>num2in my opinion
Let's try that:
num1 = 5;
num2 = 10;
num1>num2 // false
num1-num2 // -5, true
So, no, your assumption is incorrect. All results when num1 != num2 are converted to true in a boolean context, and only when num1 == num2 will the result be converted to false.
CodePudding user response:
Now I try to return
num1-num2which should equal tonum1>num2in my opinion
That is incorrect.
Is there any difference between
return num2-num1andreturn num1<num2?
Yes.
num2-num1 returns an integer value that is the result of subtracting the value of num1 from the value of num2. Since your comparator returns a bool, a result of 0 will be converted to false, and any other result will be converted to true.
num1<num2 returns a boolean value specifying whether or not num1 is actually less-than num2. Any value of num1 that is less-than the value of num2 will return true, all other values will return false.
So, as you can see, both approaches return completely different things.
std::set has the following requirement:
std::setis an associative container that contains a sorted set of unique objects of typeKey. Sorting is done using the key comparison functionCompare. Search, removal, and insertion operations have logarithmic complexity. Sets are usually implemented as red-black trees.Everywhere the standard library uses the
Comparerequirements, uniqueness is determined by using the equivalence relation. In imprecise terms, two objectsaandbare considered equivalent if neither compares less than the other:!comp(a, b) && !comp(b, a).
Using return num1<num2 (or return num1>num2) satisfies that requirement, but return num2-num1 breaks it.
For example, let's assume a = 1 and b = 2.
Using num1<num2, you get the following:
!comp(a, b) && !comp(b, a)
= !comp(1, 2) && !comp(2, 1)
= !(1 < 2) && !(2 < 1)
= !true && !false
= false && true
= one is less-than the other, so not equal, which is correct!
Using num1>num2, you get the following:
!comp(a, b) && !comp(b, a)
= !comp(1, 2) && !comp(2, 1)
= !(1 > 2) && !(2 > 1)
= !false && !true
= true && false
= one is less-than the other, so not equal, which is correct!
Using num2-num1, you get the following:
!comp(a, b) && !comp(b, a)
= !comp(1, 2) && !comp(2, 1)
= !(2 - 1) && !(1 - 2)
= !(1) && !(-1)
= !true && !true
= false && false
= neither is less-than the other, so equal, which is incorrect!
