web-dev-qa-db-fra.com

Comparaison des types polymorphes en C ++ 20

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;
}

https://godbolt.org/z/er4fsk

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?

18
MateuszL

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;
0
scohe001