c++ - 比较 C++20 中的多态类型

标签 c++ polymorphism comparison c++20 comparison-operators

我的代码介于 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/

相关文章:

Haskell:如何创建将函数应用于元组项的最通用函数

ruby-on-rails - 如何创建没有字段集的表单嵌套输入?

android - 使用 Gson2.1 和 asmx web 服务在 Json 字符串中保留多态性

javascript - 字符串比较比字符串长度快吗?

c++ - 查找数组的大小

c++ - 是否可以在运行时修改可执行文件?

c++ - 为什么 C++ 中的分号似乎隐式处理错误? [tldr : they don't]

c++ - 如何将 CString 转换为 ofstream?

comparison - BuildForge 可以做 Hudson CI 目前正在做的事情吗?

sql - T-SQL 中 varbinary 比较的性能