如何使用C++20 Ranges投影实现降序排序?
C++20范围排序:利用投影实现降序排序
现有如下Person类定义:
class Person { friend std::ostream &operator<<(std::ostream &out, const Person &operand); public: Person(std::string name, std::string address, int age, int height, int weight) : m_name(name), m_address(address), m_age(age), m_height(height), m_weight(weight) { } public: std::string m_name; std::string m_address; int m_age; int m_height; int m_weight; }; std::ostream &operator<<(std::ostream &out, const Person &operand) { out << "Person [" << operand.m_name << ", " << operand.m_age << "]"; return out; }
使用C++20的投影功能,可通过以下代码实现按年龄升序排序:
std::ranges::sort(persons, {}, &Person::m_age);
尝试以下两种写法实现降序排序时均出现编译错误:
// 错误:对成员指针做算术运算非法 std::ranges::sort(persons, {}, -1 * &Person::m_age);
// 错误:std::ranges::reverse没有接受投影参数的重载 std::ranges::reverse(persons, {}, &Person::m_age);
编译命令:
g++ "-static" -o main.exe .\*.cpp -std=c++20
正确的降序实现方式
方法1:使用反向比较器配合投影
直接传入std::ranges::greater{}作为比较器,结合投影参数即可实现降序:
std::ranges::sort(persons, std::ranges::greater{}, &Person::m_age);
std::ranges::greater{}会将投影后的值按从大到小的顺序比较,从而让原序列按年龄降序排列。
方法2:自定义lambda比较器
如果需要更灵活的逻辑,可以自定义lambda,直接比较年龄的大小:
std::ranges::sort(persons, [](const auto& a, const auto& b) { return a.m_age > b.m_age; });
这种写法也能实现降序,本质是直接比较目标属性,和投影写法的效果一致,但投影写法更简洁。
方法3:先升序再反转序列
先按升序排序,再调用std::ranges::reverse反转整个序列:
std::ranges::sort(persons, {}, &Person::m_age); std::ranges::reverse(persons);
这种方式可行,但效率略低于直接使用反向比较器,因为需要额外的反转操作。
错误写法原因说明
- 第一种错误写法试图对成员指针
&Person::m_age做算术运算,这在C++中是非法的,成员指针不支持此类数值运算。 - 第二种错误写法误用了
std::ranges::reverse,该函数仅负责反转整个序列的元素顺序,没有接受投影参数的重载,无法根据某个属性的顺序调整序列。
内容的提问来源于stack exchange,提问作者VivekDev
相关产品推荐
相关产品推荐

