Este es el código del código de la biblioteca estándar de C ++ remove
. ¿Por qué se prueba la desigualdad en if (!(*first == val))
lugar de if (*first != val)
?
template <class ForwardIterator, class T>
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator result = first;
while (first!=last) {
if (!(*first == val)) {
*result = *first;
++result;
}
++first;
}
return result;
}
operator!=
. Solo usa laoperator==
implementación:bool operator!=(const Foo& other) { return !(*this == other); }
operator==
se espera que se use aquí ...const
ejemplo en mi comentario anterior, pero entiendes el punto. (Demasiado tarde para editarlo)EqualityComparable
que Hurkyl mencionó en su respuesta .Respuestas:
Porque esto significa que el único requisito en T es implementar un
operator==
. Podría requerir que T tenga una,operator!=
pero la idea general aquí es que debe poner la menor carga posible en el usuario de la plantilla y otras plantillas sí lo necesitanoperator==
.fuente
x != y
no se define para ser lo mismo que!(x == y)
. ¿Qué sucede si estos operadores devuelven el árbol de análisis de un DSL incorporado?!=
es compatible (incorrectamente devolvería verdadero, ¡incluso sioperator==
no es compatible!). También me preocupa que pueda causar que algunos usos!=
sean ambiguos.La mayoría de las funciones en STL solo funcionan con
operator<
ooperator==
. Esto requiere que el usuario solo implemente estos dos operadores (o, a veces, al menos uno de ellos). Por ejemplo,std::set
utilizaoperator<
(más precisamente,std::less
qué invocaoperator<
por defecto) y nooperator>
para gestionar pedidos. Laremove
plantilla en su ejemplo es un caso similar: usa solooperator==
y nooperator!=
asíoperator!=
no necesita ser definido.fuente
operator<
directamente, sino que se usanstd::less
, lo que a su vez es predeterminadooperator<
.std::set
, por ejemplo , se usanoperator<
directamente. Extraño ...std::equal_to
, se usanoperator==
como se indica en la pregunta. La situación constd::less
es similar. Bueno, tal vezstd::set
no sea el mejor ejemplo.std::equal_to
ystd::less
se utilizan como parámetros de plantilla predeterminados donde el comparador se toma como parámetro.operator==
yoperator<
se usan directamente donde se requiere el tipo para satisfacer la igualdad de ordenamiento débil comparable y estricto respectivamente, por ejemplo, iteradores e iteradores de acceso aleatorio.Incorrecto. No es el
remove
código de la biblioteca estándar de C ++ . Es una posible implementación interna de laremove
función de biblioteca estándar de C ++ . El estándar C ++ no prescribe el código real; Prescribe prototipos de funciones y comportamientos requeridos.En otras palabras: desde un punto de vista estrictamente lingüístico, el código que está viendo no existe . Puede ser de algún archivo de encabezado que viene con la implementación de la biblioteca estándar de su compilador. Tenga en cuenta que el estándar C ++ ni siquiera requiere que existan esos archivos de encabezado . Los archivos son solo una forma conveniente para que los implementadores del compilador cumplan con los requisitos para una línea como
#include <algorithm>
(es decir, hacerstd::remove
y otras funciones disponibles).Porque solo
operator==
es requerido por la función.Cuando se trata de la sobrecarga del operador para tipos personalizados, el idioma le permite hacer todo tipo de cosas raras. Muy bien podría crear una clase que tenga una sobrecargada
operator==
pero no sobrecargadaoperator!=
. O peor aún: podría sobrecargarseoperator!=
pero hacer que haga cosas completamente ajenas.Considere este ejemplo:
Si se
std::remove
usaoperator!=
, el resultado sería bastante diferente.fuente
a==b
ya!=b
para devolver falso. Si bien puede que no siempre esté claro si dicha situación se consideraría de manera más significativa como "igual" o "no igual", una función que define la igualdad únicamente en términos del operador "==" debe considerarlos como "no igual" ", independientemente de qué comportamiento tendría más sentido [si tuviera mis druthers, se esperaría que todos los tipos hagan que los operadores" == "y"! = "con rendimiento booleano se comporten de manera consistente, pero el hecho de que IEEE-754 exige la igualdad rota los operadores dificultarían tal expectativa].==
y se!=
comporta de manera consistente, aunque siempre he pensado que las seis relaciones deberían evaluarfalse
cuándo es al menos un operandoNaN
.Algunas buenas respuestas aquí. Solo quería agregar una pequeña nota.
Como todas las buenas bibliotecas, la biblioteca estándar está diseñada con (al menos) dos principios muy importantes en mente:
Ponga la menor cantidad de responsabilidad en los usuarios de su biblioteca con la que pueda salirse con la suya. Parte de esto tiene que ver con darles la menor cantidad de trabajo para hacer al usar su interfaz. (como definir la menor cantidad de operadores posible). La otra parte tiene que ver con no sorprenderlos o exigirles que verifiquen los códigos de error (así que mantenga las interfaces consistentes y arroje excepciones
<stdexcept>
cuando las cosas salgan mal).Eliminar toda la redundancia lógica . Todas las comparaciones pueden deducirse simplemente de
operator<
, entonces, ¿por qué exigir que los usuarios definan a otros? p.ej:(a> b) es equivalente a (b <a)
(a> = b) es equivalente a! (a <b)
(a == b) es equivalente a! ((a <b) || (b <a))
y así.
Por supuesto, en esta nota, uno podría preguntarse por qué
unordered_map
requiereoperator==
(al menos por defecto) en lugar deoperator<
. La respuesta es que en una tabla hash, la única comparación que necesitamos es una para la igualdad. Por lo tanto, es lógicamente más consistente (es decir, tiene más sentido para el usuario de la biblioteca) exigirles que definan un operador de igualdad. Requerir unoperator<
sería confuso porque no es inmediatamente obvio por qué lo necesitarías.fuente
operator==
(yhash
).!(a==b)
. Debido a que la sobrecarga irreflexiva de los operadores puede hacer que el programa C ++ se desordene por completo (además, hacer que el programador se vuelva loco porque depurar su código puede convertirse en una misión imposible, ya que encontrar al culpable de un error en particular se parece a una odisea).!((a < b) || (b < a))
usa un operador bool menos, por lo que probablemente sea más rápidoEl
EqualityComparable
concepto solo requiere queoperator==
se defina.En consecuencia, cualquier función que profese trabajar con tipos satisfactorios
EqualityComparable
no puede depender de la existencia deoperator!=
objetos de ese tipo. (a menos que existan requisitos adicionales que impliquen la existencia deoperator!=
).fuente
De Boost FAQ: fuente
Sabiendo que requerir una
==
implementación es una carga , nunca querrás crear una carga adicional al requerir!=
implementación también.Para mí personalmente, se trata de la parte L SÓLIDA (diseño orientado a objetos): principio de sustitución de Liskov: "los objetos en un programa deben ser reemplazables con instancias de sus subtipos sin alterar la corrección de ese programa". En este caso, es el operador ! = Que puedo reemplazar con == y inversa booleana en lógica booleana.
fuente