std::ranges::sort要求自定义类型可比较或提供比较器/投影;需定义operator<、传lambda(显式类型)、或用std::less<>配合成员指针投影;不支持list等非随机访问容器。

std::ranges::sort要求自定义类型必须可比较
直接用 std::ranges::sort 对 std::vector<MyStruct> 排序会编译失败,除非 MyStruct 满足 std::totally_ordered_with<MyStruct, MyStruct>。常见错误是忘记定义 operator< 或用了 operator== 但没配对实现 operator<。
必须提供至少一种可调用的比较方式:
- 定义
friend bool operator<(const MyStruct&, const MyStruct&)(推荐,最直观) - 提供公开的
bool operator<(const MyStruct&) const - 传入自定义比较器(如 lambda),此时类型本身无需可比较
传 lambda 时要注意捕获和参数类型匹配
用 lambda 作为第三个参数最灵活,但容易因参数类型写错导致 SFINAE 失败或编译器报一堆模板错误。典型错误是写成 [&](auto a, auto b) { return a.id < b.id; } —— auto 在 lambda 参数中 C++20 不允许(除非用 C++23 的 deduced this)。
正确写法必须显式声明参数类型:
立即学习“C++免费学习笔记(深入)”;
std::ranges::sort(vec, [](const MyStruct& a, const MyStruct& b) {
return a.id < b.id;
});
如果想复用逻辑,建议用 std::less<> 配合投影(见下一条)。
用 projection 提取字段比手写 lambda 更安全
排序只依赖某个成员(比如 name 或 score)时,用 proj 参数比 lambda 更简洁、更少出错。它自动处理 const 正确性、引用绑定和返回值类型推导。
例如按 name 升序:
std::ranges::sort(vec, std::less<>{}, &MyStruct::name);
注意三点:
-
&MyStruct::name是指向数据成员的指针,不是函数调用;std::ranges::sort内部会对每个元素调用它 - 投影函数返回类型必须支持
std::less<>比较(如std::string、int) - 不能用
[](const auto& x) { return x.name; }当投影 —— 投影必须是可复制、可默认构造的函数对象,lambda 默认不可默认构造
std::ranges::sort 和 std::sort 行为一致但接口更严格
它不会改变原有容器大小,也不要求迭代器是随机访问(这点和 std::sort 一样),但它强制要求范围满足 random_access_range 和 sortable 概念。所以 std::list 不能直接用 std::ranges::sort —— 必须先转成 vector,或改用 std::list::sort()。
性能上无额外开销,底层仍是 introsort;但编译期检查更严:比如传入空 range 或 move-only 类型且没定义比较操作,会直接编译失败,而不是运行时报错。
真正容易被忽略的是:投影和比较器的组合顺序——sort(range, comp, proj) 中,proj 先作用于两个元素,再把结果交给 comp 比较。写反了就得不到预期顺序。


















