Mat*_*szL 18 c++ polymorphism comparison comparison-operators c++20
我的代码介于 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;
}
Run Code Online (Sandbox Code Playgroud)
我们现在正在迁移到 GCC-10 和 clang-10,但由于某些原因,我们仍然需要在版本 9 上工作(好吧,至少是 clang-9,因为这是 android NDK 目前拥有的)。
上面的代码停止编译,因为实现了关于比较运算符的新规则。可逆运算符== 导致歧义。我不能使用宇宙飞船运算符,因为它没有在版本 9 中实现。但我在示例中省略了这一点 - 我假设任何与 == 一起使用的东西都可以与其他运算符一起使用。
那么:在 c++20 中使用多态类型实现比较运算符的推荐方法是什么?
dfr*_*fri 19
作为中间解决方案,您可以将多态相等性重构operator==为operator==基类中定义的非虚拟,该基类以多态方式分派到非运算符虚拟成员函数:
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;
}
};
Run Code Online (Sandbox Code Playgroud)
现在将不再有歧义,因为isEqual虚拟成员函数的调度将始终在 的左侧参数上完成operator==。
const bool result = (user == machine); // user.isEqual(machine);
Run Code Online (Sandbox Code Playgroud)