std::ranges::subrange 是满足 view 概念的轻量迭代器对封装,直接构造无需容器;支持随机访问迭代器时自动提供 size();需显式指定哨兵类型防推导失败;无 make_subrange,非 range-v3 兼容。

std::ranges::subrange 本质就是迭代器对的视图封装
它不是“转换成”视图,而是直接以 std::ranges::subrange 类型存在——它本身就是一个满足 std::ranges::view 概念的轻量对象。只要传入合法的迭代器(begin 和 end),就能立刻获得一个可组合、可传递、零开销的视图。
最简构造:用两个迭代器直接初始化
常见错误是试图先构造容器再取 std::ranges::subrange,其实完全没必要。只要手头有迭代器(比如 std::vector 的 begin()/end()),一行就能包好:
std::vector<int> v = {1, 2, 3, 4, 5};
auto r = std::ranges::subrange(v.begin(), v.end()); // 类型是 subrange<vector<int>::iterator>
- 支持所有满足
std::input_iterator的迭代器类型(包括const_iterator) - 如果已知迭代器是
std::random_access_iterator(如std::vector、std::string),subrange会自动启用size()成员函数 - 不拷贝元素,不分配内存,仅存两个指针/迭代器 + 可选的 size(取决于模板推导)
避免隐式类型推导陷阱:显式指定哨兵类型
当 end 是哨兵(sentinel)而非同类型迭代器时(例如 std::string_view::end() 是 std::string_view::iterator,但某些自定义范围可能用不同类型的哨兵),仅靠 auto 推导可能失败或退化为非 view 类型。
此时应显式使用带哨兵模板参数的构造:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
std::string_view sv = "hello"; auto r = std::ranges::subrange(sv.begin(), sv.end(), sv.size()); // 强制启用 size 版本 // 或更通用: auto r2 = std::ranges::subrange<std::string_view::iterator, std::string_view::iterator>(sv.begin(), sv.end());
- 省略第三个参数(
count)时,若迭代器不支持operator-,size()不可用 - 传入
std::ranges::dangling{}作为哨兵(如处理临时字符串的end())需额外小心生命周期 - 用
decltype查看实际类型:结果可能是subrange<I, S, K>,其中K是std::ranges::subrange_kind枚举(unsized或sized)
和 range-v3 的 make_subrange 不兼容,别混用
C++20 的 std::ranges::subrange 是类型,不是工厂函数。没有 std::ranges::make_subrange —— 这是 range-v3 的旧习惯,C++20 标准里不存在该函数。
- 写
std::ranges::subrange{it, end}是标准且唯一的构造方式 - 误写
std::ranges::make_subrange(...)会导致编译错误:error: 'make_subrange' is not a member of 'std::ranges' - 若项目还在用 range-v3,注意命名空间冲突:
ranges::subrange(v3)和std::ranges::subrange(C++20)行为略有差异,尤其在 ADL 和隐式转换上
真正要小心的是迭代器有效性——subrange 不管理底层数据生命周期,一旦原容器析构或重分配,它的迭代器立刻悬空。这不是封装问题,而是所有视图的共性约束。

















