std::ranges::equal_range是c++20引入的范围适配版二分查找算法,返回subrange(本质pair),其begin()和end()分别指向有序范围内所有等于目标值的元素首尾;它与std::equal_range功能一致,但接受范围而非迭代器对,自动推导比较逻辑,默认用operator

std::ranges::equal_range 是什么,它和 std::equal_range 有什么区别
std::ranges::equal_range 是 C++20 引入的范围适配版二分查找算法,作用是返回一个 std::ranges::subrange(本质是 std::pair),其 begin() 和 end() 分别指向有序范围内所有等于给定值的元素的首尾迭代器。它和传统的 std::equal_range 行为一致,但支持范围(std::ranges::range)而非迭代器对,且自动推导比较逻辑(默认用 ,可传 <code>comp)。
关键区别在于调用方式:旧版要传 first/last 迭代器;新版直接传容器或视图,更简洁、更难出错。
- 必须确保输入范围已排序(升序,默认),否则行为未定义
- 不支持自定义比较器时,元素类型需满足
std::totally_ordered_with<t t></t> - 返回类型是
std::ranges::subrange<it></it>,不是std::pair<it it></it>(尽管语义等价,但成员访问需用.begin()/.end())
怎么写最简可用代码:vector + int 查找
以下是最常见使用场景:在 std::vector<int></int> 中查找所有值为 5 的连续位置。
std::vector<int> v = {1, 2, 4, 5, 5, 5, 6, 8};
auto [first, last] = std::ranges::equal_range(v, 5); // C++20 结构化绑定
// first 指向第一个 5,last 指向最后一个 5 的后一个位置
std::cout
<ul>
<li>必须用 C++20 或更高标准编译(<code>-std=c++20</code>)</li>
<li>不能对 <code>std::array</code> 或原生数组直接传名(如 <code>arr</code>),需转成视图:<code>std::ranges::equal_range(std::span{arr})</code> 或 <code>std::ranges::equal_range(std::views::all(arr))</code>
</li>
<li>若不用结构化绑定,可写为 <code>auto r = std::ranges::equal_range(v, 5); auto first = r.begin(); auto last = r.end();</code>
</li>
</ul>
<h3>自定义比较器怎么传:查找忽略大小写的字符串</h3>
<p>当元素不是基础类型,或需要非默认序(如按长度、忽略大小写)时,必须显式传比较器。注意:比较器签名必须是 <code>bool( const T&, const U& )</code> 或 <code>bool( const U&, const T& )</code>,且需满足 strict weak ordering。</p>
<pre class="brush:php;toolbar:false;">std::vector<:string> words = {"apple", "Banana", "cherry", "Date"};
auto r = std::ranges::equal_range(words, "banana",
[](const std::string& a, const std::string& b) {
return std::lexicographical_compare(
a.begin(), a.end(),
b.begin(), b.end(),
[](char x, char y) { return std::tolower(x) 等价形式)</:string>
- 比较器必须对所有可能的
a和b都有定义,否则 UB - 不要在比较器里修改参数或依赖外部状态(如全局变量)
- 如果容器按长度排序,而你想查长度为 5 的字符串,则比较器应写成
[](const std::string& s, int len) { return s.size() —— 第二个参数类型可以不同
常见错误:为什么返回的 range 是空的,但元素明明存在
最常踩的坑不是语法,而是语义误判:返回空 range(first == last)只代表“没找到匹配值”,并不一定意味着值不存在——它只说明没有满足 !comp(value, elem) && !comp(elem, value) 的元素(即既不大于也不小于,严格等于)。
- 排序用的比较器和
equal_range传的不一致 → 结果不可靠(例如排序用std::greater,查找却用默认) - 容器未真正排序(比如插入后没调用
std::sort)→ 行为未定义,可能返回任意迭代器 - 浮点数直接比较:由于精度问题,
equal_range很难命中精确相等,应改用带 tolerance 的自定义比较器,或改用lower_bound+ 手动扫描 - 传了
std::views::filter等非随机访问视图 → 编译失败(equal_range要求范围满足std::random_access_range)
实际调试时,先用 std::ranges::is_sorted(v, comp) 验证排序有效性,再查比较器是否双向兼容。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











