std::min
and std::max
allows custom comparators, but I am a bit confused on how the ordering works.
Consider the following:
int i = 1;
int j = 2;
auto min_val = min(i, j, [](const auto val1, const auto val2){
if(val1 < val2) return true;
return false;
});
This returns the minimum value, which is i
. But I don't understand why we use the <
instead of the >
, and why val1
and val2
appear on the left and right of the operand, respectively.
Consider the following:
int i = 1;
int j = 2;
auto max_val = max(i, j, [](const auto val1, const auto val2){
if(val1 > val2) return true;
return false;
});
I was thinking that this would return the maximum value, but it actually returns the minimum value, and again, we must use the <
operand. Could someone explain what is going on beneath the hood?
I've run into this issue on some other stuff too, I think with std::priority_queue
and std::map
, where the ordering and comparison operators aren't very intuitive to me, and most times I have to guess and check to get what I want.
That basically boils down to how those functions are defined in the standard. std::max
, for example, defines the comparer (your lambda) as follows:
comparison function object (i.e. an object that satisfies the requirements of Compare) which returns true if a is less than b.
Usually, when it comes to the order of values within the c++ standard library, it's (almost?) always std::less
that is used as a default comparer, which does exactly left < right
.
As to why it's always a < b
that has to be satisfied I think it's simply to reduce coding overhead if you were to write it yourself. Imagine having a comparer like this:
struct MyComp
{
bool operator()(MyType a, MyType b) const
{
return a.getValue() < b.getValue();
}
};
Since all the constructs in the standard library require your comparer to return true, if a < b
, you can use one simple comparer for a multitude of constructs. E.g.
auto maxVal = std::max(a, b, MyComp{});
auto minVal = std::min(a, b, MyComp{});
std::map<MyType, MyComp> myMap;
will all just work with one comparer.