C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Standard attribute [[nocompare]] for defaulted comparisons

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Tue, 17 Jan 2023 10:40:28 -0500
On Mon, Jan 16, 2023 at 11:14 PM Jason McKesson via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Mon, Jan 16, 2023 at 10:56 PM Arthur O'Dwyer via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
> > On Mon, Jan 16, 2023 at 4:26 PM joeri _ via Std-Proposals <
> std-proposals_at_[hidden]> 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

Received on 2023-01-17 15:40:42