sort libreria example ejemplo cstdlib algorithms c++ algorithm set

c++ - libreria - ¿Es seguro usar operator!=As operator<en un estándar:: set?



sort algorithm c++ (4)

Tengo una estructura con algunos miembros y tengo un operador implementado == para ello. ¿Es seguro implementar el operador <con la ayuda del operador ==? Quiero usar esta estructura en un conjunto, y quiero verificar que esta estructura sea única.

struct Data { std::string str1; std::string str2; std::string str3; std::string str4; bool operator==(const Data& rhs) { if (str1 == rhs.str1 && str2 == rhs.str2 && str3 == rhs.str3 && str4 == rhs.str4 ) return true; else return false; } // Is this ok?? bool operator<(const Data& rhs) { return !this->operator==(rhs); } }

Entonces, cuando inserto esta estructura en un estándar, ¿qué pasará?


Bueno, tu código sugiere que si A!=B , eso significa que A<B es definitivamente incorrecto, ya que también puede ser A>B

Tendrá que implementar sus operadores > y < la misma manera que lo hizo con el operator== , lo que significa al comparar los objetos en forma de miembro. Depende de usted decidir cómo determinar si A es "más" o "menos" que B según sus miembros.

Si usa el operador como lo tiene en cualquiera de los contenedores de biblioteca estándar, obtendrá UB.


Necesita definir operator< en sus propios términos. No puede implementar operator< en términos de operator== , aunque puede hacer lo contrario.

Considera la paradoja en esta tabla de verdad:

"a" < "b" : TRUE "b" < "a" : TRUE

Si su implementación de operator< produce la paradoja anterior, que lo hace si la implementa en términos de operator== entonces no ha implementado correctamente un orden débil estricto. Lo que has implementado es un desastre.

Debe determinar cuál de las cadenas miembro tiene prioridad sobre las demás, y luego realizar una comparación entre ellas en orden, de mayor a menor importancia.

Por ejemplo, si la precedencia de la cadena es, de lo más importante a lo menos importante:

  1. str1
  2. str2
  3. str3
  4. str4

... entonces esto produce el siguiente algoritmo para el operator< :

bool operator<(const Data& rhs) const { if( str1 < rhs.str1 ) return true; if( rhs.str1 < str1 ) return false; if( str2 < rhs.str2 ) return true; if( rhs.str2 < str2 ) return false; if( str3 < rhs.str3 ) return true; if( rhs.str3 < str3 ) return false; if( str4 < rhs.str4 ) return true; if( rhs.str4 < str4 ) return false; return false; }

Utilizando esto, podría opcionalmente volver a implementar operator== en términos de operator< . Sin embargo, usted asume la ineficiencia inherente de la complejidad del tiempo al hacerlo:

bool operator==(const Data& rhs) const { return !operator<(rhs) && !rhs.operator<(*this); }


No, es bastante inseguro. La forma más sencilla de implementarlo es a través de std::tie .

#include <tuple> struct Data { std::string str1; std::string str2; std::string str3; std::string str4; bool operator<(const Data& rhs) const // you forgot a const { return std::tie(str1, str2, str3, str4) < std::tie(rhs.str1, rhs.str2, rhs.str3, rhs.str4); } }


No, eso no es seguro. La forma en que ha definido < , a < b y b < a serán ambas verdaderas al mismo tiempo.

Entonces, cuando inserto esta estructura en un estándar, ¿qué pasará?

El comportamiento no está definido, por lo que todo está permitido, y es probable que sea diferente en diferentes implementaciones.