Search code examples
c++setlesscomparator

C++, why does std::set allow lower_bound() on a type different than that of the set elements, but only if I add less<> in the set declaration?


I have this class with an overloaded comparator:

struct Foo {
    int x;
    bool operator < (Foo other) const {
        return x < other.x;
    }
    bool operator < (int val) const {
        return x < val;
    }
};

and I make a set on it:

set<Foo> s;

I'm allowed to call lower_bound() on a Foo, but not on an int (as you would expect).

s.lower_bound(Foo{3}); // works
s.lower_bound(3); //"no matching member function for call to 'lower_bound'

But if instead I declare s with a less<> :

set<Foo,less<>>

Both calls work:

s.lower_bound({3});
s.lower_bound(3);

Why?


Solution

  • why does std::set allow lower_bound() on a type different than that of the set elements

    Because it is useful, and potentially more efficient.

    Consider for example a set of std::strings. Creating (large) strings is expensive. If you have a string view, you can use std::less<> to compare the view to the strings of the set without having to construct a string from that view.

    but only if I add less<> in the set declaration?

    Because the second type parameter, to which you passed std::less<> as the argument is the functor that the set uses to compare the elements. std::less<> is what is able to compare objects of different types. The default comparator is std::less<T> which can only compare objects of type T. std::less<> isn't the default because it didn't exist when std::set was standardised.