How do I iterate equal values with the standard library?
You can use std::upper_bound
to get the iterator to the "next" value. Since std::upper_bound
returns an iterator to the first element greater than that value provided, if you provide the value of the current element, it will give you an iterator that will be one past the end of the current value. That would give you a loop like
iterator it = v.begin();
while (it != v.end()) {
iterator b = it;
iterator e = std::upper_bound(it, v.end(), *it);
for (iterator i=b; i!=e; ++i) {
// do something with i
}
it = e; // need this so the loop starts on the next value
}
This is basically Range v3's group_by
: group_by(v, std::equal_to{})
. It doesn't exist in the C++17 standard library, but we can write our own rough equivalent:
template <typename FwdIter, typename BinaryPred, typename ForEach>
void for_each_equal_range(FwdIter first, FwdIter last, BinaryPred is_equal, ForEach f) {
while (first != last) {
auto next_unequal = std::find_if_not(std::next(first), last,
[&] (auto const& element) { return is_equal(*first, element); });
f(first, next_unequal);
first = next_unequal;
}
}
Usage:
for_each_equal_range(v.begin(), v.end(), std::equal_to{}, [&] (auto first, auto last) {
for (; first != last; ++first) {
// Do something with each element.
}
});