How to use lower_bound() on set of pairs?
The core issue is that your std::set
instance is already sorted, but with the default std::pair
operator<
. You cannot intuitively use the member function std::set::lower_bound
, as this uses the comparison function of its class type. You can't use std::lower_bound
with a custom predicate neither, as this assumes a sorted range - but sorted with respect to the given predicate, which is not the case.
But there is a workaround for this specific scenario. Note that for each value of x
in the set, the minimal associated value of y
is the minimal value of type int
. As the comparison operator for std::pair
instances does a member-wise comparison, you can combine this to:
#include <set>
#include <limits>
const std::set<std::pair<int,int>> s{
{42, 0}, {42, 1}, {43, 0}, {43, 1}
};
const auto entry = s.lower_bound({43, std::numeric_limits<int>::min()});
This will always find the first or minimal desired entry in the subset that correspond to the given value for the std::pair::first
data member. Only the first value is of significance, as the second one is immediately not less than std::numeric_limits<int>::min()
, which is what lower_bound
is searching for.
If you need this functionality many times, it might be worth putting it into its own helper function (template), e.g.
template <class T>
auto lower_bound_first(const std::set<std::pair<T, T>>& s, T first)
{
static constexpr T min = std::numeric_limits<T>::min();
return s.lower_bound({first, min});
}
which you can invoke as
const auto entry = lower_bound_first(s, 43);
for any underlying value types for which the std::numeric_limits
specialization is available.