https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115699

            Bug ID: 115699
           Summary: Anonymous structs should compare member-wise with
                    C++20 defaulted operator==
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mital at mitalashok dot co.uk
  Target Milestone: ---

Consider:

```
struct A {
  struct {
    int i;
  };
  friend bool operator==(A, A) = default;
};
static_assert(A{} == A{});
```

This currently fails as the operator== is marked as deleted since it tries to
compare the anonymous struct members as a whole:

```
<source>:7:24: error: use of deleted function 'constexpr bool operator==(A, A)'
    7 | static_assert(A{} == A{});
      |                        ^
<source>:5:15: note: 'constexpr bool operator==(A, A)' is implicitly deleted
because the default definition would be ill-formed:
    5 |   friend bool operator==(A, A) = default;
      |               ^~~~~~~~
<source>:2:3: error: no match for 'operator==' (operand types are 'A::<unnamed
struct>' and 'A::<unnamed struct>')
    2 |   struct {
      |   ^~~~~~
<source>:5:15: note: candidate: 'constexpr bool operator==(A, A)' (deleted)
    5 |   friend bool operator==(A, A) = default;
      |               ^~~~~~~~
<source>:5:26: note:   no known conversion for argument 1 from 'A::<unnamed
struct>' to 'A'
    5 |   friend bool operator==(A, A) = default;
      |                          ^
```

This is a GCC/C11 extension so there is no "official" expected behaviour, but
this is surprising. This also leads to overload resolution being done with the
unnamed struct type:

```
struct X {
    struct {
        bool b;
    };
    bool c;
    template<typename T>
    friend constexpr bool operator==(T& L, T& R) {
        // T is the type of the anonymous struct
        static_assert(sizeof(T) == sizeof(bool));
        return L.b == R.b;
    }
    friend constexpr bool operator==(const X& L, const X& R) = default;
};

static_assert(X{} == X{});
```

Where it might make more sense for each member of the anonymous struct to be
considered a member of the class the struct is declared in so when operator==
compares member by member, it compares each member of the anonymous struct.

(This also applies to defaulted operator<=>)

Reply via email to