c++ - ¿Por qué se requiere const para ''operador>'' pero no para ''operador<''?
sorting operator-overloading (2)
El uso de
std::sort(vec.begin(), vec.end())
depende solo de la función del
operator<
.
No requiere que la función pueda trabajar con objetos
const
.
std::greater
, por otro lado, requiere que la función pueda trabajar con objetos
const
.
Verá un problema similar si usa
std::less
, como
std::sort(vec.begin(), vec.end(), std::less<MyStruct>())
.
Dicho esto, no hay razón para que la función
operator<
función y la función
operator>
sean funciones miembro no
const
.
Cualquier función miembro que no modifique los datos del miembro debe convertirse en una función miembro
const
.
Considere esta pieza de código:
#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;
}
}
Se compila bien y da el resultado que cabría esperar. Pero si trato de ordenar las estructuras en orden descendente:
#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;
}
}
Esto me da un error. Aquí está el mensaje completo :
/usr/include/c++/7.2.0/bits/stl_function.h: en la instanciación de ''constexpr bool std :: Greater <_Tp> :: operator () (const _Tp &, const _Tp &) const [with _Tp = MyStruct]'' :
/usr/include/c++/7.2.0/bits/stl_function.h:376:20: error: no coincide con ''operator>'' (los tipos de operando son ''const MyStruct'' y ''const MyStruct'')
{return __x> __y; }
Parece ser porque esta función aquí no tiene un calificador
const
:
bool operator > (const MyStruct& other) {
return (key > other.key);
}
Si lo agrego,
bool operator > (const MyStruct& other) const {
return (key > other.key);
}
Entonces todo vuelve a estar bien.
¿Por qué esto es tan?
No estoy muy familiarizado con la sobrecarga del operador, así que lo acabo de guardar en la memoria para que necesitemos agregar la
const
pero aún es extraño por qué funciona para el
operator<
sin la
const
.
Obtiene comportamientos diferentes porque de hecho está llamando a dos funciones de sort diferentes (sobrecargadas).
En el primer caso, llama a los dos parámetros
std::sort
, que usa el
operator<
directamente.
Dado que los iteradores de sus elementos vectoriales producen referencias no constantes, puede aplicar el
operator<
muy bien.
En el segundo caso, está utilizando la versión de tres parámetros de
std::sort
.
El que acepta un functor.
Usted pasa
std::greater
.
Y ese functor tiene un
operator()
declarado de la siguiente manera:
constexpr bool operator()( const T& lhs, const T& rhs ) const;
Tenga en cuenta las referencias constantes.
Vincula los elementos que necesita comparar con las referencias constantes.
Por lo tanto, su propio
operator>
debe ser constante.
Si
std::sort
llamar a
std::sort
con
std::less
, su
operator<
producirá el mismo error, porque no es constante.