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