Dites que je travaille avec une classe:
class Foo{
public:
std:string name;
/*...*/
}/*end Foo*/
et je fournis une surcharge pour operator==
bool operator==(const Foo& fooObj, const std::string& strObj) {
return (fooObj.name == strObj);
}
Dois-je également ré-implémenter la même logique en sens inverse?
bool operator==(const std::string& strObj, const Foo& fooObj) {
return (strObj == fooObj.name);
}
(C++ 20 et ultérieur)
Avec l'acceptation de p1185 en C++ 20, vous n'avez pas besoin de fournir plus d'une surcharge. Le papier a apporté ces modifications (entre autres) à la norme:
[over.match.oper]
.4 - [...] Pour l'opérateur
!=
([expr.eq]), les candidats réécrits incluent tous les candidats membres, non membres et intégrés de l'opérateur==
pour lequel l'expression réécrite(x == y)
est bien formée lors de la conversion contextuelle en objet booléen à l'aide de l'opérateur==
. Pour les opérateurs d'égalité, les candidats réécrits incluent également un candidat synthétisé, avec l'ordre des deux paramètres inversé, pour chaque membre, membre non membre et candidat intégré de l'opérateur==
pour lequel l'expression réécrite(y == x)
est bien formé lors de la conversion contextuelle en booléen à l'aide de l'opérateur==
. [Remarque: un candidat synthétisé à partir d'un candidat membre a son paramètre d'objet implicite comme second paramètre. Par conséquent, les conversions implicites sont prises en compte pour le premier paramètre, mais pas pour le second. - note de fin] [...]8 [...] Si un candidat réécrit est sélectionné par la résolution de surcharge pour un opérateur
!=
,x != y
est interprété comme(y == x) ? false : true
si le candidat sélectionné est un candidat synthétisé avec ordre inverse des paramètres, ou(x == y) ? false : true
sinon, en utilisant le candidat sélectionnéoperator==
réécrit. Si un candidat réécrit est sélectionné par la résolution de surcharge pour un opérateur==
,x == y
est interprété comme(y == x) ? true : false
à l'aide du candidatoperator==
réécrit sélectionné.
Ce qui précède signifie que non seulement et non devez fournir à l'opérateur l'ordre des opérandes inversé, vous obtenez également !=
gratuitement! De plus, la fonction operator==
peut être membre si cela a du sens. Bien que, comme l'indique la note du premier paragraphe ci-dessus, le fait d'être membre ou une fonction libre affectera les conversions implicites. Vous devez donc en tenir compte.
(Jusqu'à C++ 17)
Vous le faites si vous voulez prendre en charge les comparaisons où la chaîne est à gauche et le Foo
à droite. Une implémentation ne réorganisera pas les arguments vers un operator==
surchargé pour le faire fonctionner.
Toutefois, vous pouvez éviter de répéter la logique de la mise en œuvre. En supposant que votre opérateur doit se comporter comme prévu:
inline bool operator==(const std::string& objA, const Foo& objB) {
return objB == objA; // Reuse previously defined operator
}
Oui vous Comme dans beaucoup d'autres langages, C++ prend parti et les comparaisons entre deux objets de types différents mèneront à des appels à deux opérateurs de comparaison différents en fonction de l'ordre.
Bien sûr, vous voulez qu'ils soient cohérents et sans surprise, donc le second doit être défini en termes de premier.