Since C++20 the compiler can generate default comparison operators for a class, including as friend non-member function, see (2) in cppreference.com.
I came across the code working in MSVC that does it for a local class inside a function:
void foo() {
struct A;
bool operator ==(const A&, const A&);
struct A {
friend bool operator ==(const A&, const A&) = default;
};
}
Unfortunately, it does not work in Clang or GCC, which complains:
error: cannot define friend function 'operator==' in a local class definition
Online demo: https://godbolt.org/z/Ts1fer1d1
There is a way to make the code accepted by GCC:
void foo() {
struct A;
bool operator ==(const A&, const A&);
struct A {
friend bool operator ==(const A&, const A&);
};
bool operator ==(const A&, const A&) = default;
}
which now only prints some vague warning:
warning: declaration of 'bool operator==(const foo()::A&, const foo()::A&)' has 'extern' and is initialized
but the other two compilers does not like it, online demo: https://godbolt.org/z/he1zjj46G
As long as the compilers diverge, which one is correct in both examples above?
The standard is very clear on this:
A function may be defined in a friend declaration of a class if and only if the class is a non-local class and the function name is unqualified.
Your first code sample is defining a friend
in a local class, so it violates this paragraph.
The second example defines a function at block scope, which is also clearly ill-formed:
[...] A function shall be defined only in namespace or class scope. [...]
The fact that GCC compiles it is a compiler bug, and possibly related to the fact that GCC supports local functions as a compiler extension. The warning has 'extern' and is initialized
it gives is nonsensical, and would normally occur in scenarios such as:
// <source>:1:12: warning: 'x' initialized and declared 'extern'
// 1 | extern int x = 0;
// | ^
extern int x = 0;
Note: I've filed a bug report for this problem: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111079