std::ranges::sort 要求传入符合 random_access_range 概念的范围而非裸指针对,正确用法包括:对容器直接传参、C数组用 std::span、指针区间用 std::ranges::subrange;自定义比较函数须满足严格弱序。

std::ranges::sort 不能直接对 C 风格数组或裸指针排序,必须传入迭代器范围(std::ranges::iterator_t 可推导的范围),否则编译失败。
为什么 std::ranges::sort 会报错 “no matching function”
常见错误是传入两个裸指针(如 sort(p, p + n))或 C 数组名(如 sort(arr, arr + 5))。C++20 的 std::ranges::sort 要求第一个参数是符合 std::ranges::random_access_range 概念的类型,而非单独的迭代器对。
正确做法是用范围适配器或显式构造视图:
- 对
std::vector、std::array等容器:直接传容器本身 ——std::ranges::sort(vec) - 对 C 风格数组:用
std::span包裹 ——std::ranges::sort(std::span(arr)) - 对指针区间:用
std::ranges::subrange或std::views::take——std::ranges::sort(std::ranges::subrange(p, p + n))
自定义比较函数必须满足 strict weak ordering
传入的 comp 参数(如 std::ranges::sort(v, std::greater{}))不能返回 true 当两参数相等,否则行为未定义。尤其注意浮点数比较、自定义结构体中字段为 NaN 或未初始化时的逻辑漏洞。
常见陷阱:
- 写成
[](auto a, auto b) { return a → 违反非自反性(comp(x,x)为true) - 在 lambda 中捕获局部变量并修改其状态 → 多次调用间状态不一致,导致排序崩溃或无限循环
- 使用
std::less(即{})时,若元素类型无operator 或三路比较支持,编译失败
std::ranges::sort 和 std::sort 性能几乎一致,但语义更安全
底层仍调用 introsort(混合快排/堆排/插排),没有额外运行时开销。区别在于:std::ranges::sort 在编译期检查范围有效性(比如是否可随机访问)、比较函数是否满足概念约束,提前暴露错误。
实际影响:
- 对
std::list调用std::ranges::sort直接编译失败(不满足random_access_range),而std::sort可能静默编译但运行时报错 - 传入
std::vector::const_iterator会失败 —— 因为 const 迭代器不支持赋值(排序需修改元素),这点比老接口更严格 - 不支持原地稳定排序;如需稳定,必须用
std::ranges::stable_sort
调试时遇到 “concept not satisfied” 别急着改代码
这个错误通常不是你写错了,而是传入对象的类型没公开满足必要概念。例如:
- 自定义容器未提供
begin()/end()成员函数,或返回类型不满足std::input_iterator - 重载了
operator 但声明为private或在匿名命名空间里,ADL 找不到 - 用了
std::vector—— 它的迭代器不是真正的随机访问迭代器,std::ranges::sort拒绝接受
此时最有效的方法是用 static_assert 检查概念:static_assert(std::ranges::random_access_range,再逐层看哪个约束断了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











