默认实现的虚拟“运算符 <=>”是否会在 C++20 中多出一个虚拟方法?

Fed*_*dor 10 c++ comparison-operators language-lawyer c++20

如果使用默认实现创建virtualC++20 三路比较运算符,则编译器会默默地创建一个 virtual ,如在子类中重写它所示:<=>operator==

struct A { 
    virtual std::strong_ordering operator <=>(const A &) const = default; 
};
struct B : A {
    virtual bool operator==(const A&) const noexcept override;
};
Run Code Online (Sandbox Code Playgroud)

所有三个主要编译器的行为都是如此,演示:https://gcc.godbolt.org/z/nvaf94M51

它是标准规定的还是只是一种常见的实施实践?

作为一个侧面观察,在 C++20 中我们也有能力创建consteval立即虚拟函数,如果扩展示例:

#include <compare>

struct A { 
    virtual consteval std::strong_ordering operator <=>(const A &) const = default; 
};

struct B : A {
    virtual consteval bool operator==(const A&) const noexcept override { return false; }
};

int main() {
    static constexpr B b;
    static constexpr const A & a = b;
    static_assert( (a <=> a) == 0 );
    static_assert( a != a );
    return (a <=> a) == 0; 
}
Run Code Online (Sandbox Code Playgroud)

那么它给现代编译器带来了一定的困难:https://gcc.godbolt.org/z/Gsz39Kr5b

Clang 崩溃,GCC 生成一个程序,该程序在执行过程中失败。这些只是一些编译器错误,还是程序格式不正确?

Lan*_*yer 6

\n

它是标准规定的还是只是一种常见的实施实践?

\n
\n

这是强制性的。[class.compare.default]/5 :

\n
\n

如果成员规范未显式声明任何名为 的成员或友元operator==,则为成员规范==中定义为默认值的每个三向比较运算符函数隐式声明一个运算符函数,具有相同的访问权限和函数定义,并且在相同的类范围作为相应的三向比较运算符函数,只不过返回类型替换为,声明符 ID替换为。booloperator==

\n

[注2:此类隐式声明的==类运算符X在 的定义中被定义为默认值X,并且具有与相应的三向比较运算符相同的参数声明子句和尾随要求子句friend。\n它是用、virtualconstexpr、 或consteval如果三向比较运算符函数是这样声明的。... \xe2\x80\x94 尾注]

\n

[示例1

\n
template<typename T> struct X {\n friend constexpr std::partial_ordering operator<=>(X, X) requires (sizeof(T) != 1) = default;\n // implicitly declares: friend constexpr bool operator==(X, X) requires (sizeof(T) != 1) = default;\n\n [[nodiscard]] virtual std::strong_ordering operator<=>(const X&) const = default;\n // implicitly declares: [[nodiscard]] virtual bool operator==(const X&) const = default;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x80\x94结束示例]

\n
\n