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:
- [class.friend] p6
Your first code sample is defining a
friendin a local class, so it violates this paragraph.The second example defines a function at block scope, which is also clearly ill-formed:
- [dcl.fct.def.general] p2
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 initializedit gives is nonsensical, and would normally occur in scenarios such as:Note: I've filed a bug report for this problem: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111079