Je rencontre un comportement étrange avec le nouvel opérateur de vaisseau spatial <=>
en C ++ 20. J'utilise le compilateur Visual Studio 2019 avec /std:c++latest
.
Ce code se compile très bien, comme prévu:
#include <compare>
struct X
{
int Dummy = 0;
auto operator<=>(const X&) const = default; // Default implementation
};
int main()
{
X a, b;
a == b; // OK!
return 0;
}
Cependant, si je change X en ceci:
struct X
{
int Dummy = 0;
auto operator<=>(const X& other) const
{
return Dummy <=> other.Dummy;
}
};
J'obtiens l'erreur de compilation suivante:
error C2676: binary '==': 'X' does not define this operator or a conversion to a type acceptable to the predefined operator
J'ai également essayé ceci sur clang, et j'obtiens un comportement similaire.
J'apprécierais quelques explications sur la raison pour laquelle l'implémentation par défaut génère operator==
correctement, mais pas celle personnalisée.
la source
Lors de la standardisation de cette fonctionnalité, il a été décidé que l'égalité et l'ordre devraient être logiquement séparés. En tant que tel, les utilisations des tests d'égalité (
==
et!=
) ne seront jamais invoquéesoperator<=>
. Cependant, il était toujours considéré comme utile de pouvoir par défaut les deux avec une seule déclaration. Donc, si vous par défautoperator<=>
, il a été décidé que vous vouliez également par défautoperator==
(à moins que vous ne le définissiez plus tard ou que vous l'ayez défini plus tôt).Quant à savoir pourquoi cette décision a été prise , le raisonnement de base est le suivant. Considérez
std::string
. L'ordre de deux chaînes est lexicographique; chaque caractère a sa valeur entière comparée à chaque caractère de l'autre chaîne. La première inégalité résulte du résultat de la commande.Cependant, le test d'égalité des chaînes a un court-circuit. Si les deux chaînes ne sont pas de longueur égale, alors il n'y a aucun intérêt à faire une comparaison par caractère; ils ne sont pas égaux. Donc, si quelqu'un fait des tests d'égalité, vous ne voulez pas le faire en long et en large si vous pouvez le court-circuiter.
Il s'avère que de nombreux types nécessitant un ordre défini par l'utilisateur offriront également un mécanisme de court-circuit pour les tests d'égalité. Pour empêcher les gens d'implémenter uniquement
operator<=>
et de gâcher les performances potentielles, nous forçons efficacement chacun à faire les deux.la source
Les autres réponses expliquent très bien pourquoi la langue est comme ça. Je voulais juste ajouter que dans le cas où ce n'est pas évident, il est bien sûr possible d'avoir un utilisateur fourni
operator<=>
avec un défautoperator==
. Vous avez juste besoin d'écrire explicitement la valeur par défautoperator==
:la source