On Mon, Jan 16, 2023 at 11:14 PM Jason McKesson via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Mon, Jan 16, 2023 at 10:56 PM Arthur O'Dwyer via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
> On Mon, Jan 16, 2023 at 4:26 PM joeri _ via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
>>
>> The introduction of a standard attribute [[nocompare]] which can be used to indicate that a suboject of T should be omitted from a defaulted comparison.
[...]
That being said, the attribute syntax has an advantage: it can play
around with structural types. At present, you can overload
`operator==` for structural types, but they don't matter; equality for
template instantiation purposes only cares about binary equality. If
we allow attributes to turn off a member's equality, we could allow
such types to remain structural, just ignoring the members that aren't
compared.

I believe that paragraph is entirely misguided. Structural types do comparison by mangling the entire contents of the object into a string and then comparing (and hashing) those strings; it has nothing to do with the object's `operator==` at all. Equality is a property of values; structural comparison is a property of contents.
For example:
https://godbolt.org/z/KEeff17xE (a structural type with a defaulted `operator==`; constexpr evaluation says two objects are "equal," but they mangle differently)
https://godbolt.org/z/vYEzbqeza (an enum type with a customized `operator==`; constexpr evaluation uses the `operator==` and reports "unequal," but the manglings are the same)
(and yes, I talked about this in https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1837r0.html back in 2019, this isn't news to anyone on WG21)

I don't believe it would be physically sensical at all to have part of an object's contents "ignored" by mangling. How would you get at those contents within the template, then?

struct W {
    [[nocompare]] int i;
    int j;
};
template<W w> void foo() {
    int a[w.j];  // OK
    int b[w.i];  // must also be OK, right?
}
// IIUC, you wanted these two instantiations of `foo` to be the same instantiation:
void foo<W{10,20}>();  // How big is array `b` inside this instantiation? 10?
void foo<W{20,20}>();  // How big is array `b` inside this instantiation? 20? How can they be the same instantiation, then?

–Arthur