我的代码介于 c++17 和 c++20 之间。具体来说,我们在 GCC-9 和 clang-9 上启用了 c++20,它只是部分实现。
在代码中,我们有相当大的多态类型层次结构,如下所示:
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我们现在正在迁移到 GCC-10 和 clang-10,但由于某些原因,我们仍然需要在版本 9 上工作(好吧,至少是 clang-9,因为这是 android NDK 目前所拥有的)。
上面的代码停止编译,因为实现了关于比较运算符的新规则。可逆运算符== 会导致歧义。我不能使用 spaceship 运算符,因为它没有在版本 9 中实现。但是我在示例中省略了这一点 - 我假设任何适用于 == 的东西都适用于其他运算符。
所以:
在 c++20 中使用多态类型实现比较运算符的推荐方法是什么?
最佳答案
作为中间解决方案,您可以重新考虑多态相等 operator==
到非虚拟 operator==
在基类中定义,它多态地分派(dispatch)给一个非操作符的虚成员函数:
struct Identifier {
bool operator==(const Identifier& other) const {
return isEqual(other);
}
private:
virtual bool isEqual(const Identifier& other) const = 0;
};
// Note: do not derive this class further (less dyncasts may logically fail).
struct UserIdentifier final : public Identifier {
int userId = 0;
private:
virtual bool isEqual(const Identifier& other) const override {
const UserIdentifier *otherUser = dynamic_cast<const UserIdentifier*>(&other);
return otherUser && otherUser->userId == userId;
}
};
// Note: do not derive this class further (less dyncasts may logically fail).
struct MachineIdentifier final : public Identifier {
int machineId = 0;
private:
virtual bool isEqual(const Identifier& other) const override {
const MachineIdentifier *otherMachine = dynamic_cast<const MachineIdentifier*>(&other);
return otherMachine && otherMachine->machineId == machineId;
}
};
现在,isEqual
上的调度将不再有歧义。虚拟成员函数将始终在 operator==
的左侧参数上完成.const bool result = (user == machine); // user.isEqual(machine);
关于c++ - 比较 C++20 中的多态类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64544936/