Il s'agit du code du code de la bibliothèque standard C ++ remove
. Pourquoi les inégalités sont-elles testées au if (!(*first == val))
lieu 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!=
. Utilisez simplement l'operator==
implémentation:bool operator!=(const Foo& other) { return !(*this == other); }
operator==
on s'attend à ce qu'ils soient utilisés ici ...const
dans l'exemple de mon commentaire précédent, mais vous comprenez. (Trop tard pour le modifier)EqualityComparable
que Hurkyl a mentionné dans sa réponse .Réponses:
Parce que cela signifie que la seule exigence sur T est d'implémenter un
operator==
. Vous pourriez demander à T d'avoir un,operator!=
mais l'idée générale ici est que vous devriez mettre le moins de charge possible sur l'utilisateur du modèle et que d'autres modèles en ont besoinoperator==
.la source
x != y
n'est pas défini comme étant identique à!(x == y)
. Que faire si ces opérateurs renvoient l'arborescence d'analyse d'un DSL intégré?!=
est pris en charge (retournerait incorrectement true - même s'iloperator==
n'est pas pris en charge!). Je crains également que certaines utilisations de!=
deviennent ambiguës.La plupart des fonctions de STL fonctionnent uniquement avec
operator<
ouoperator==
. Cela oblige l'utilisateur à implémenter uniquement ces deux opérateurs (ou parfois au moins l'un d'entre eux). Par exemplestd::set
utiliseoperator<
(plus précisémentstd::less
qui invoqueoperator<
par défaut) et nonoperator>
pour gérer la commande. Leremove
modèle dans votre exemple est un cas similaire - il utilise uniquementoperator==
et nonoperator!=
donc leoperator!=
n'a pas besoin d'être défini.la source
operator<
directement mais utilisent à la placestd::less
, ce qui à son tour est par défautoperator<
.std::set
, utilisent effectivementoperator<
directement. Strange ...std::equal_to
, elles utilisentoperator==
comme indiqué dans la question. La situation avecstd::less
est similaire. Eh bien, cestd::set
n'est peut - être pas le meilleur exemple.std::equal_to
etstd::less
sont utilisés comme paramètres de modèle par défaut où le comparateur est pris comme paramètre.operator==
etoperator<
sont utilisés directement lorsque le type est requis pour satisfaire respectivement une égalité comparable et un ordre faible strict, par exemple des itérateurs et des itérateurs à accès aléatoire.Faux. Ce n'est pas le
remove
code de la bibliothèque standard C ++ . C'est une implémentation interne possible de laremove
fonction de bibliothèque standard C ++ . La norme C ++ ne prescrit pas de code réel; il prescibe les prototypes de fonction et les comportements requis.En d'autres termes: du point de vue du langage strict, le code que vous voyez n'existe pas . Cela peut provenir d'un fichier d'en-tête fourni avec l'implémentation de la bibliothèque standard de votre compilateur. Notez que la norme C ++ n'exige même pas que ces fichiers d'en- tête existent. Les fichiers sont juste un moyen pratique pour les implémenteurs de compilateurs de répondre aux exigences d'une ligne comme
#include <algorithm>
(c'est-à-dire rendrestd::remove
et d'autres fonctions disponibles).Parce que seul
operator==
est requis par la fonction.En ce qui concerne la surcharge d'opérateurs pour les types personnalisés, le langage vous permet de faire toutes sortes de choses étranges. Vous pouvez très bien créer une classe qui a un fichier surchargé
operator==
mais pas surchargéoperator!=
. Ou pire encore: vous pourriez surchargeroperator!=
mais lui faire faire des choses totalement indépendantes.Prenons cet exemple:
Si
std::remove
utiliséoperator!=
, le résultat serait tout à fait différent.la source
a==b
eta!=b
de renvoyer false. S'il n'est pas toujours clair si une telle situation serait plus significativement considérée comme "égale" ou "non-égale", une fonction qui définit l'égalité uniquement en fonction de l'opérateur "==" doit les considérer comme "non égales" ", quel que soit le comportement qui aurait le plus de sens [si j'avais mes druthers, tous les types seraient censés faire en sorte que les opérateurs" == "et"! = "produisant des valeurs booléennes se comportent de manière cohérente, mais le fait que IEEE-754 impose une égalité rompue les opérateurs rendraient cette attente difficile].==
et!=
se comporte de manière cohérente, même si j'ai toujours pensé que les six relations devraient être évaluées àfalse
quand au moins un opérande estNaN
.Quelques bonnes réponses ici. Je voulais juste ajouter une petite note.
Comme toutes les bonnes bibliothèques, la bibliothèque standard est conçue avec (au moins) deux principes très importants à l'esprit:
Mettez le moins de responsabilité possible sur les utilisateurs de votre bibliothèque avec lesquels vous pouvez vous en tirer. Une partie de cela a à voir avec leur donner le moins de travail à faire lors de l'utilisation de votre interface. (comme définir le moins d'opérateurs possible). L'autre partie est de ne pas les surprendre ou de les obliger à vérifier les codes d'erreur (alors gardez les interfaces cohérentes et jetez des exceptions
<stdexcept>
lorsque les choses tournent mal).Éliminez toute redondance logique . Toutes les comparaisons peuvent être déduites simplement de
operator<
, alors pourquoi exiger que les utilisateurs définissent les autres? par exemple:(a> b) équivaut à (b <a)
(a> = b) équivaut à! (a <b)
(a == b) équivaut à! ((a <b) || (b <a))
etc.
Bien sûr sur cette note, on pourrait se demander pourquoi
unordered_map
requiertoperator==
(au moins par défaut) plutôt queoperator<
. La réponse est que dans une table de hachage, la seule comparaison dont nous ayons jamais besoin est celle pour l'égalité. Il est donc plus cohérent logiquement (c'est-à-dire plus logique pour l'utilisateur de la bibliothèque) de lui demander de définir un opérateur d'égalité. Exiger unoperator<
serait déroutant car il n'est pas immédiatement évident de savoir pourquoi vous en auriez besoin.la source
operator==
(ethash
).!(a==b)
. Parce qu'une surcharge non réfléchie des opérateurs peut facilement causer un désordre complet du programme C ++ (en plus, rendre le programmeur fou car le débogage de son code peut devenir une mission impossible, car trouver le coupable d'un bogue particulier ressemble à une odyssée).!((a < b) || (b < a))
utilise un opérateur booléen de moins, donc c'est probablement plus rapideLe
EqualityComparable
concept ne demande qu'àoperator==
être défini.Par conséquent, toute fonction qui prétend travailler avec des types satisfaisants
EqualityComparable
ne peut pas s'appuyer sur l'existence deoperator!=
for objets de ce type. (sauf s'il existe des exigences supplémentaires qui impliquent l'existence deoperator!=
).la source
De Boost FAQ: source
Sachant que la
==
mise en œuvre est un fardeau , vous ne voulez jamais créer de charge supplémentaire en exigeant également la!=
mise en œuvre.Pour moi personnellement, il s'agit de SOLID (conception orientée objet) Partie L - principe de substitution de Liskov: «les objets d'un programme doivent être remplaçables par des instances de leurs sous-types sans altérer l'exactitude de ce programme.». Dans ce cas c'est l'opérateur ! = Que je peux remplacer par == et l' inverse booléen en logique booléenne.
la source