Date: Mon, 16 Jan 2023 22:56:33 -0500
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.
>
>
>
> struct s {
>
> int id;
>
> [[nocompare]] std::string name;
>
> auto operator<=>(s const&) const = default;
>
> };
>
This wouldn't be a good use of an attribute — not because "attributes
should be ignorable," but mainly because attributes are (like keywords)
*expensive* to specify and implement and teach. It seems like there ought
to be a clever way to get this behavior without any language extensions.
The first thing that came to mind was to wrap `name_` in a helper type that
would always compare equal; something like this:
struct S {
int id_;
struct Helper {
std::string name_;
auto operator<=>(const Helper&) const { return
std::strong_ordering::equal; }
auto operator==(const Helper&) const { return true; }
} h;
auto operator<=>(const S&) const = default;
};
You can even get the inner `<=>` and `==` for free(-ish) by making `Helper`
inherit from `std::monostate`, or any other type whose `operator<=>` does
the right thing.
// https://godbolt.org/z/v4nzKjbb5
struct S {
int id_;
struct Helper : std::monostate {
Helper(std::string n) : name_(std::move(n)) {}
std::string name_;
} h;
S(int id, std::string name) : id_(id), h(std::move(name)) {}
auto operator<=>(const S&) const = default;
};
I'm not saying this solution *as-is* should be considered better or cleaner
than `[[nocompare]] std::string name_;` — but it suggests to me that there
is *some* clever idiom waiting to be discovered here within the current
language.
The basic principle here is "Rule of Zero": strive to =default all your
special members, including the "honorary" special members `<=>` and `==`.
That means if you don't want some field to participate in the comparison
(or to be copied, or to be swapped, or whatever), you should pull it out
into a helper class so that the top-level business-logic class can simply
=default its special members.
–Arthur
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.
>
>
>
> struct s {
>
> int id;
>
> [[nocompare]] std::string name;
>
> auto operator<=>(s const&) const = default;
>
> };
>
This wouldn't be a good use of an attribute — not because "attributes
should be ignorable," but mainly because attributes are (like keywords)
*expensive* to specify and implement and teach. It seems like there ought
to be a clever way to get this behavior without any language extensions.
The first thing that came to mind was to wrap `name_` in a helper type that
would always compare equal; something like this:
struct S {
int id_;
struct Helper {
std::string name_;
auto operator<=>(const Helper&) const { return
std::strong_ordering::equal; }
auto operator==(const Helper&) const { return true; }
} h;
auto operator<=>(const S&) const = default;
};
You can even get the inner `<=>` and `==` for free(-ish) by making `Helper`
inherit from `std::monostate`, or any other type whose `operator<=>` does
the right thing.
// https://godbolt.org/z/v4nzKjbb5
struct S {
int id_;
struct Helper : std::monostate {
Helper(std::string n) : name_(std::move(n)) {}
std::string name_;
} h;
S(int id, std::string name) : id_(id), h(std::move(name)) {}
auto operator<=>(const S&) const = default;
};
I'm not saying this solution *as-is* should be considered better or cleaner
than `[[nocompare]] std::string name_;` — but it suggests to me that there
is *some* clever idiom waiting to be discovered here within the current
language.
The basic principle here is "Rule of Zero": strive to =default all your
special members, including the "honorary" special members `<=>` and `==`.
That means if you don't want some field to participate in the comparison
(or to be copied, or to be swapped, or whatever), you should pull it out
into a helper class so that the top-level business-logic class can simply
=default its special members.
–Arthur
Received on 2023-01-17 03:56:46