Pourquoi const est-il requirejs pour ‘operator>’ mais pas pour ‘operator <'?

Considérez ce morceau de code:

#include  #include  #include  #include  using namespace std; struct MyStruct { int key; std::ssortingng ssortingngValue; MyStruct(int k, const std::ssortingng& s) : key(k), ssortingngValue(s) {} bool operator < (const MyStruct& other) { return (key < other.key); } }; int main() { std::vector  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 comstack bien et donne la sortie à laquelle on s’attend. Mais si j’essaie de sortinger les structures par ordre décroissant:

 #include  #include  #include  #include  using namespace std; struct MyStruct { int key; std::ssortingng ssortingngValue; MyStruct(int k, const std::ssortingng& s) : key(k), ssortingngValue(s) {} bool operator > (const MyStruct& other) { return (key > other.key); } }; int main() { std::vector  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()); 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 :: larger :: 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 ‘operator>’ (les types d’opérandes sont ‘const MyStruct’ et ‘const MyStruct’)
{return __x> __y; }

Cela semble être dû au fait que cette fonction 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); } 

Alors tout va bien à nouveau. Pourquoi cela est-il ainsi? Je ne suis pas trop familier avec la surcharge des opérateurs, donc je viens de mettre en mémoire le fait que nous devons append le const mais il est toujours étrange que cela fonctionne pour operator< sans const .

Vous obtenez des comportements différents car vous appelez en fait deux fonctions de sorting différentes (surchargées).

Dans le premier cas, vous appelez le paramètre std::sort , qui utilise l’ operator< directement. Les iterators de vos éléments vectoriels produisant des références non const, ils peuvent appliquer l' operator< très bien.

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

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

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

Si vous deviez appeler std::sort avec std::less , votre operator< produirait la même erreur, car ce n'est pas correct.

L’utilisation de std::sort(vec.begin(), vec.end()) ne dépend que de la fonction operator< . Il ne nécessite pas que la fonction soit capable de travailler avec des objects const .

std::greater , d'autre part, nécessite que la fonction soit capable de travailler avec des objects const .

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


Cela dit, il n’ya aucune raison pour que la fonction operator< function et la fonction operator> soient des fonctions de membre non const . Toute fonction membre qui ne modifie pas les données des membres doit devenir une fonction membre const .