web-dev-qa-db-fra.com

Pourquoi const est-il requis pour 'opérateur>' mais pas pour 'opérateur <'?

Considérons ce morceau de code:

#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;
    }
}

Il compile bien et donne le résultat attendu. Mais si j'essaie de trier les structures par ordre décroissant:

#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;
    }
}

Cela me donne une erreur. Voici le message complet :

/usr/include/c++/7.2.0/bits/stl_function.h: en instanciation de 'constexpr bool std :: supérieur <_Tp> :: operator () (const _Tp &, const _Tp &) const [avec _Tp = MyStruct]' :
/usr/include/c ++/7.2.0/bits/stl_function.h: 376: 20: erreur: pas de correspondance pour 'opérateur>' (les types d'opérande sont 'const MyStruct' et 'const MyStruct')
{return __x> __y; }

Cela semble être dû au fait que cette fonction ici n’a pas de qualificatif const:

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

Si je l'ajoute,

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

Ensuite, tout va bien à nouveau. Pourquoi cela est-il ainsi? Je ne connais pas trop la surcharge d'opérateur, je viens donc de le mettre en mémoire. Nous devons donc ajouter le const, mais c'est toujours étrange pourquoi cela fonctionne pour operator< sans le const.

56
Rockstar5645

Vous obtenez des comportements différents parce que vous appelez en fait deux fonctions différentes (surchargées) sort .

Dans le premier cas, vous appelez les deux paramètres std::sort, Qui utilisent directement operator<. Etant donné que les itérateurs de vos éléments vectoriels produisent des références non constantes, cela peut très bien s'appliquer operator<.

Dans le second cas, vous utilisez la version à trois paramètres de std::sort. Celui qui accepte un foncteur. Vous passez std::greater. Et ce foncteur a une operator() déclarée comme suit:

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

Notez les références const. Il lie les éléments à comparer aux références const. Donc, votre propre operator> Doit également être correct.

Si vous appeliez std::sort Avec std::less , votre operator< Produirait la même erreur, car ce n'est pas const-correct.

83
StoryTeller

L'utilisation de std::sort(vec.begin(), vec.end()) ne dépend que de la fonction operator<. Il n'est pas nécessaire que la fonction puisse fonctionner avec les objets const.

std::greater, En revanche, nécessite que la fonction puisse fonctionner avec les objets const.

Vous verrez un problème similaire si vous utilisez std::less, Tel que std::sort(vec.begin(), vec.end(), std::less<MyStruct>()).


Cela dit, il n'y a aucune raison pour que la fonction operator< Et la fonction operator> Soient des fonctions non -const member. Toute fonction membre qui ne modifie pas les données de membre doit devenir une fonction membre const.

25
R Sahu