J'ai du code qui est quelque part entre C++ 17 et C++ 20. Plus précisément, nous avons activé C++ 20 activé sur GCC-9 et Clang-9, où il n'est que partiellement mis en œuvre.
Dans le code, nous avons une assez grande hiérarchie de types polymorphes comme celui-ci:
struct Identifier {
virtual bool operator==(const Identifier&other) const = 0;
};
struct UserIdentifier : public Identifier {
int userId =0;
bool operator==(const Identifier&other) const override {
const UserIdentifier *otherUser = dynamic_cast<const UserIdentifier*>(&other);
return otherUser && otherUser->userId == userId;
}
};
struct MachineIdentifier : public Identifier {
int machineId =0;
bool operator==(const Identifier&other) const override {
const MachineIdentifier *otherMachine = dynamic_cast<const MachineIdentifier*>(&other);
return otherMachine && otherMachine->machineId == machineId;
}
};
int main() {
UserIdentifier user;
MachineIdentifier machine;
return user==machine? 1: 0;
}
Nous migrons actuellement vers GCC-10 et CLANG-10, mais pour des raisons pour des raisons de travailler sur les versions 9 (bien, au moins CLANG-9, car c'est ce que Android NDK a actuellement ).
Le code ci-dessus arrête la compilation car de nouvelles règles sur les opérateurs de comparaison sont mises en œuvre. Opérateur réversible == provoque des ambiguïtés. Je ne peux pas utiliser un opérateur de vaisseau spatial car il n'est pas implémenté dans les versions 9. Mais j'ai omis cela de l'exemple - je suppose que tout ce qui fonctionne avec == travaillera avec d'autres opérateurs.
Ainsi: Quelle est l'approche recommandée de la mise en œuvre des opérateurs de comparaison en C++ 20 avec des types polymorphes?
Vous n'avez pas de polymorphisme dans votre code. Vous pouvez forcer une liaison dynamique de la fonction de comparaison de l'opérateur (polymorphisme) à l'aide de Identifier
pointeurs ou de références.
Par exemple, au lieu de
UserIdentifier user;
MachineIdentifier machine;
return user==machine? 1: 0;
Avec des références que vous pourriez faire:
UserIdentifier user;
MachineIdentifier machine;
Identifier &iUser = user;
return iUser == machine ? 1: 0;
Inversement, vous pouvez expliquer explicitement UserIdentifier
's opérateur de comparaison:
return user.operator==(machine) ? 1: 0;