3

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?

1
  • 1
    For the first part, #2 in en.cppreference.com/w/cpp/language/friend indicates that it's only valid to have an inline definition for a friend if the class is non-local, and ...=default; is a definition. So gcc and clang are correct. For the second part, again ...=default; is a definition and you cannot have a function definition in block scope, so I believe it is also invalid. Commented Aug 19, 2023 at 21:22

1 Answer 1

3

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.

- [class.friend] p6

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. [...]

- [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 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

Sign up to request clarification or add additional context in comments.

1 Comment

GCC supports local functions as a compiler extension Not in C++

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.