libc++ 对 std::map/set::equal_range 的实现给出了意想不到的结果

libc++'s implementation of std::map/set::equal_range gives unexpected results

本文关键字:实现 结果 意想不到 range std map equal set libc++      更新时间:2023-10-16

我注意到 clang 的 libc++ 中的std::set::equal_range(与std::map相同(给出的结果与 libstdc++ 不同。 我一直认为equal_range应该返回等效的std::make_pair(set.lower_bound(key), set.upper_bound(key))这就是 cppreference 所说的和 libstdc++ 所做的。 然而,在libc ++中,我有一个代码给出了不同的结果。

#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;
}

正如您在 https://rextester.com/CLTS82056 中看到的,这给出了

equal_range returned 1 elem(s): 3 
lower/upper returned 2 elem(s): 3 6 

使用libstdc++boost::container::set,我在这两种情况下都会得到 2 个元素(我期望(。

当然,我可以在我的代码中手动调用lower_boundupper_bound,但使用equal_range更短,清楚地表明了我的意图(我想找到属于给定范围的所有元素(并且可能更快(因为equal_range该方法可以编码为一个树遍历,而无需实际调用lower_boundupper_bound(。

有趣的是,在这种情况下将容器类型更改为std::multiset会使equal_range返回 2 个元素。

现在这是libc++中的错误还是 cpp首选项在 https://en.cppreference.com/w/cpp/container/set/equal_range 中给出了错误的提示:

或者,第一个迭代器可以用lower_bound()得到,第二个迭代器可以用upper_bound()得到。

你的代码很好。

您正在测试过时的libc ++。这是错误 30959,于 2018 年修复,可在 clang 7 中使用。

Rextester的叮当显然是3.8。