11 Classes [class]

11.10 Comparisons [class.compare]

11.10.1 Defaulted comparison operator functions [class.compare.default]

A defaulted comparison operator function ([expr.spaceship], [expr.rel], [expr.eq]) for some class C shall be a non-template function declared in the member-specification of C that is
  • a non-static const member of C having one parameter of type const C&, or
  • a friend of C having two parameters of type const C&.
If the class definition does not explicitly declare an == operator function, but declares a defaulted three-way comparison operator function, an == operator function is declared implicitly with the same access as the three-way comparison operator function.
The implicitly-declared == operator for a class X is an inline member and is defined as defaulted in the definition of X.
If the three-way comparison operator function is declared as a non-static const member, the implicitly-declared == operator function is a member of the form
bool X::operator==(const X&) const;
Otherwise, the implicitly-declared == operator function is of the form
friend bool operator==(const X&, const X&);
[Note
: Such a friend function is visible to argument-dependent lookup ([basic.lookup.argdep]) only ([namespace.memdef]). —end note
]
The operator is a constexpr function if its definition would satisfy the requirements for a constexpr function.
[Note
:
The == operator function is declared implicitly even if the defaulted three-way comparison operator function is defined as deleted.
end note
]
A type C has strong structural equality if, given a glvalue x of type const C, either:
  • C is a non-class type and x <=> x is a valid expression of type std::strong_­ordering or std::strong_­equality, or
  • C is a class type with an == operator defined as defaulted in the definition of C, x == x is well-formed when contextually converted to bool, all of C's base class subobjects and non-static data members have strong structural equality, and C has no mutable or volatile subobjects.
The direct base class subobjects of C, in the order of their declaration in the base-specifier-list of C, followed by the non-static data members of C, in the order of their declaration in the member-specification of C, form a list of subobjects.
In that list, any subobject of array type is recursively expanded to the sequence of its elements, in the order of increasing subscript.
Let be an lvalue denoting the element in the expanded list of subobjects for an object x (of length n), where is formed by a sequence of derived-to-base conversions ([over.best.ics]), class member access expressions ([expr.ref]), and array subscript expressions ([expr.sub]) applied to x.
It is unspecified whether virtual base class subobjects appear more than once in the expanded list of subobjects.