具有默认实现的虚拟`operator <=>`是否在C ++ 20中增加了一个虚拟方法?
Does virtual `operator <=>` with default implementation make one more virtual method in C++20?
如果使用默认实现制作 virtual
C++20 three-way 比较运算符 <=>
,则编译器会默默地制作一个虚拟 operator==
,因为可以通过在 child class:
中覆盖它来显示
struct A {
virtual std::strong_ordering operator <=>(const A &) const = default;
};
struct B : A {
virtual bool operator==(const A&) const noexcept override;
};
所有三个主要编译器都以这种方式运行,演示: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;
}
然后它给现代编译器带来了一定的困难:https://gcc.godbolt.org/z/Gsz39Kr5b
Clang 崩溃,GCC 生成一个程序,该程序在执行过程中失败。这些只是一些编译器错误,还是程序格式不正确?
Is it mandated by the standard or just a common implementation practice?
这是强制性的。 [class.compare.default]/5:
If the member-specification does not explicitly declare any member or friend named operator==
, an ==
operator function is declared implicitly for each three-way comparison operator function defined as defaulted in the member-specification, with the same access and function-definition and in the same class scope as the respective three-way comparison operator function, except that the return type is replaced with bool
and the declarator-id is replaced with operator==
.
[Note 2: Such an implicitly-declared ==
operator for a class X
is defined as defaulted in the definition of X
and has the same parameter-declaration-clause and trailing requires-clause as the respective three-way comparison operator.
It is declared with friend
, virtual
, constexpr
, or consteval
if the three-way comparison operator function is so declared. ... — end note]
[Example 1:
template<typename T> struct X {
friend constexpr std::partial_ordering operator<=>(X, X) requires (sizeof(T) != 1) = default;
// implicitly declares: friend constexpr bool operator==(X, X) requires (sizeof(T) != 1) = default;
[[nodiscard]] virtual std::strong_ordering operator<=>(const X&) const = default;
// implicitly declares: [[nodiscard]] virtual bool operator==(const X&) const = default;
};
— end example]
如果使用默认实现制作 virtual
C++20 three-way 比较运算符 <=>
,则编译器会默默地制作一个虚拟 operator==
,因为可以通过在 child class:
struct A {
virtual std::strong_ordering operator <=>(const A &) const = default;
};
struct B : A {
virtual bool operator==(const A&) const noexcept override;
};
所有三个主要编译器都以这种方式运行,演示: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;
}
然后它给现代编译器带来了一定的困难:https://gcc.godbolt.org/z/Gsz39Kr5b
Clang 崩溃,GCC 生成一个程序,该程序在执行过程中失败。这些只是一些编译器错误,还是程序格式不正确?
Is it mandated by the standard or just a common implementation practice?
这是强制性的。 [class.compare.default]/5:
If the member-specification does not explicitly declare any member or friend named
operator==
, an==
operator function is declared implicitly for each three-way comparison operator function defined as defaulted in the member-specification, with the same access and function-definition and in the same class scope as the respective three-way comparison operator function, except that the return type is replaced withbool
and the declarator-id is replaced withoperator==
.[Note 2: Such an implicitly-declared
==
operator for a classX
is defined as defaulted in the definition ofX
and has the same parameter-declaration-clause and trailing requires-clause as the respective three-way comparison operator. It is declared withfriend
,virtual
,constexpr
, orconsteval
if the three-way comparison operator function is so declared. ... — end note][Example 1:
template<typename T> struct X { friend constexpr std::partial_ordering operator<=>(X, X) requires (sizeof(T) != 1) = default; // implicitly declares: friend constexpr bool operator==(X, X) requires (sizeof(T) != 1) = default; [[nodiscard]] virtual std::strong_ordering operator<=>(const X&) const = default; // implicitly declares: [[nodiscard]] virtual bool operator==(const X&) const = default; };
— end example]