为什么'operator>'需要const但不是'运营商<'?

时间:2018-02-20 05:45:32

标签: c++ sorting operator-overloading

考虑这段代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

struct MyStruct
{
    int key;
    std::string stringValue;

    MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

    bool operator < (const MyStruct& other) {
        return (key < other.key);
    }
};

int main() {
    std::vector < MyStruct > vec;

    vec.push_back(MyStruct(2, "is"));
    vec.push_back(MyStruct(1, "this"));
    vec.push_back(MyStruct(4, "test"));
    vec.push_back(MyStruct(3, "a"));

    std::sort(vec.begin(), vec.end());

    for (const MyStruct& a : vec) {
        cout << a.key << ": " << a.stringValue << endl;
    }
}

它编译得很好并且给出了预期的输出。但是,如果我尝试按降序对结构进行排序:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

struct MyStruct
{
    int key;
    std::string stringValue;

    MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

    bool operator > (const MyStruct& other) {
        return (key > other.key);
    }
};


int main() {
    std::vector < MyStruct > vec;

    vec.push_back(MyStruct(2, "is"));
    vec.push_back(MyStruct(1, "this"));
    vec.push_back(MyStruct(4, "test"));
    vec.push_back(MyStruct(3, "a"));

    std::sort(vec.begin(), vec.end(), greater<MyStruct>());

    for (const MyStruct& a : vec) {
        cout << a.key << ": " << a.stringValue << endl;
    }
}

这给了我一个错误。 Here is the full message

  

/ usr / include / c ++ / 7.2.0 / bits / stl_function.h:实例化'constexpr bool std :: greater&lt; _Tp&gt; :: operator()(const _Tp&amp;,const _Tp&amp;)const [with _Tp = MyStruct]':
  /usr/include/c++/7.2.0/bits/stl_function.h:376:20:错误:'运营商&gt;'不匹配(操作数类型是'const MyStruct'和'const MyStruct')
         {return __x&gt; __y; }

似乎是因为这里的这个功能没有const限定符:

bool operator > (const MyStruct& other) {
        return (key > other.key);
}

如果我添加它,

bool operator > (const MyStruct& other) const {
        return (key > other.key);
}

然后一切都很好。为什么会这样?我不太熟悉运算符重载,所以我只是把它放在内存中我们需要添加const但是它仍然很奇怪为什么它适用于没有operator<的{​​{1}}

2 个答案:

答案 0 :(得分:81)

您会遇到不同的行为,因为您实际上正在调用两个不同的(重载)sort函数。

在第一种情况下,您调用两个参数std::sort,它直接使用operator<。由于向量元素的迭代器产生非const引用,因此它可以很好地应用operator<

在第二种情况下,您使用的是std::sort的三参数版本。接受仿函数的那个​​。你通过了std::greater。该仿函数的operator()声明如下:

constexpr bool operator()( const T& lhs, const T& rhs ) const;

注意const引用。它绑定了与const引用进行比较所需的元素。所以你自己的operator>也必须是正确的。

如果您使用std::less致电std::sort,则operator<会产生相同的错误,因为它不是常规错误。

答案 1 :(得分:24)

std::sort(vec.begin(), vec.end())的使用仅取决于operator<功能。它不要求该函数能够使用const个对象。

另一方面,

std::greater要求该函数能够使用const个对象。

如果您使用std::less,则会发现类似的问题,例如std::sort(vec.begin(), vec.end(), std::less<MyStruct>())

话虽如此,operator<函数和operator>函数没有理由成为非const成员函数。任何不修改成员数据的成员函数都应该成为const成员函数。