如何对UDT Vector降序排序?重载operator>报错解决方案
问题描述
我需要对自定义类型Point的vector进行降序排序,于是在Point类中重载了operator>运算符,并用sort搭配greater<Point>()执行排序,但编译报错,错误提示传递const Point*作为this参数丢弃了限定符。
原代码
#include <bits/stdc++.h> using namespace std; class Point { public: int x; int y; Point(int x = 0, int y = 0) { this->x = x; this->y = y; } bool operator>(const Point &p1) { return (x + y) > (p1.x + p1.y); } }; int main() { vector<Point> v = {{1, 2}, {3, 1}, {0, 1}}; sort(v.begin(), v.end(), greater<Point>()); for (auto i : v) cout << i.x << " " << i.y << endl; return 0; }
错误信息
In file included from /opt/compiler-explorer/gcc-trunk-20221128/include/c++/13.0.0/string:49,
from /opt/compiler-explorer/gcc-trunk-20221128/include/c++/13.0.0/bitset:52,
from /opt/compiler-explorer/gcc-trunk-20221128/include/c++/13.0.0/x86_64-linux-gnu/bits/stdc++.h:52,
from:1:
/opt/compiler-explorer/gcc-trunk-20221128/include/c++/13.0.0/bits/stl_function.h: In instantiation of 'constexpr bool std::greater<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = Point]':
/opt/compiler-explorer/gcc-trunk-20221128/include/c++/13.0.0/bits/predefined_ops.h:158:30: required from 'constexpr bool __gnu_cxx::__ops::_Iter_comp_iter<_Compare>::operator()(_Iterator1, _Iterator2) [with _Iterator1 = __gnu_cxx::__normal_iterator<Point*, std::vector>; _Iterator2 = __gnu_cxx::__normal_iterator<Point*, std::vector >; _Compare = std::greater ]'
/opt/compiler-explorer/gcc-trunk-20221128/include/c++/13.0.0/bits/stl_algo.h:1819:14: required from 'void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Point*, vector>; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<greater >]'
/opt/compiler-explorer/gcc-trunk-20221128/include/c++/13.0.0/bits/stl_algo.h:1859:25: required from 'void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Point*, vector>; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<greater >]'
/opt/compiler-explorer/gcc-trunk-20221128/include/c++/13.0.0/bits/stl_algo.h:1950:31: required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Point*, vector>; _Compare = __gnu_cxx::__ops::_Iter_comp_iter<greater >]'
/opt/compiler-explorer/gcc-trunk-20221128/include/c++/13.0.0/bits/stl_algo.h:4893:18: required from 'void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<Point*, vector>; _Compare = greater ]' :27:9: required from here /opt/compiler-explorer/gcc-trunk-20221128/include/c++/13.0.0/bits/stl_function.h:398:20: error: no match for 'operator>' (operand types are 'const Point' and 'const Point') 398 | { return __x > __y; } | ~~~~^~~~~ :17:10: note: candidate: 'bool Point::operator>(const Point&)' (near match) 17 | bool operator>(const Point &p1) | ^~~~~~~~ :17:10: note: passing 'const Point*' as 'this' argument discards qualifiers
错误原因
std::greater<Point>的operator()会接收两个const引用的Point对象,调用__x > __y时,__x是const对象。但你的operator>成员函数没有被标记为const,意味着编译器认为它可能会修改调用对象的状态,因此不允许在const对象上调用这个非const成员函数,最终抛出"丢弃const限定符"的错误。
解决方案
方案1:修改operator>为const成员函数
给operator>添加const修饰符,明确告知编译器该函数不会修改调用对象的状态,允许在const对象上调用:
bool operator>(const Point &p1) const { return (x + y) > (p1.x + p1.y); }
完整修改后的代码:
#include <bits/stdc++.h> using namespace std; class Point { public: int x; int y; Point(int x = 0, int y = 0) { this->x = x; this->y = y; } // 添加const修饰符 bool operator>(const Point &p1) const { return (x + y) > (p1.x + p1.y); } }; int main() { vector<Point> v = {{1, 2}, {3, 1}, {0, 1}}; sort(v.begin(), v.end(), greater<Point>()); for (auto i : v) cout << i.x << " " << i.y << endl; return 0; }
方案2:使用自定义lambda比较器
如果不想修改Point类的成员函数,可以直接给sort传递lambda表达式作为比较器,这种方式更灵活,适合仅在特定场景需要自定义排序的情况:
#include <bits/stdc++.h> using namespace std; class Point { public: int x; int y; Point(int x = 0, int y = 0) { this->x = x; this->y = y; } }; int main() { vector<Point> v = {{1, 2}, {3, 1}, {0, 1}}; // 使用lambda作为自定义比较器 sort(v.begin(), v.end(), [](const Point& a, const Point& b) { return (a.x + a.y) > (b.x + b.y); }); for (auto i : v) cout << i.x << " " << i.y << endl; return 0; }
内容的提问来源于stack exchange,提问作者Rushabh Laddha

