I noticed std::set::equal_range (same for std::map) in clang's libc++ gives different result than libstdc++.
I always assumed equal_range should return equivalent of std::make_pair(set.lower_bound(key), set.upper_bound(key)) which is what cppreference says and libstdc++ does.
In libc++ however I have a code which gives a different result.
#include <set>
#include <iostream>
#include <iterator>
struct comparator {
using range_t = std::pair<int, int>;
using is_transparent = std::true_type;
bool operator()(int lhs, int rhs) const
{
return lhs < rhs;
}
bool operator()(int lhs, range_t rhs) const
{
return lhs < rhs.first;
}
bool operator()(range_t lhs, int rhs) const
{
return lhs.second < rhs;
}
};
using range_set = std::set<int, comparator>;
int main()
{
range_set set = { 1, 3, 6, 10 };
auto range = comparator::range_t{2, 7};
auto eq = set.equal_range(range);
auto low = set.lower_bound(range);
auto high = set.upper_bound(range);
std::cout << "equal_range returned " << std::distance(eq.first, eq.second) << " elem(s): ";
std::copy(eq.first, eq.second, std::ostream_iterator<int>(std::cout, " "));
std::cout << "\nlower/upper returned " << std::distance(low, high) << " elem(s): ";
std::copy(low, high, std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
return 0;
}
As you can see at https://rextester.com/CLTS82056 this gives
equal_range returned 1 elem(s): 3
lower/upper returned 2 elem(s): 3 6
With libstdc++ as well as with boost::container::set I get 2 elements (which I expect) in both cases.
Of course I can manually call lower_bound and upper_bound in my code but using equal_range is shorter, clearly shows my intention (I want to find all elements which fall into the given range) and might be faster (because equal_range method could be coded as one tree traversal without actual calls to lower_bound and upper_bound).
Interestingly enough, changing container type to std::multiset in this case makes equal_range return 2 elements.
Now is this a bug in libc++ or does cppreference give wrong hint in https://en.cppreference.com/w/cpp/container/set/equal_range:
Alternatively, the first iterator may be obtained with
lower_bound(), and the second withupper_bound().
Your code is fine.
You are testing on an outdated libc++. This is bug 30959, fixed in 2018 and available in clang 7.
Rextester's clang is apparently 3.8.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With