web-dev-qa-db-fra.com

En C ++, devez-vous surcharger l'opérateur == dans les deux sens?

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);
}
55
hehe3301

(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 candidat operator== 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
}
76
StoryTeller

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.

6
Matthieu Brucher