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