"The Problem" indeed exists in real-word code, but imo it's caused by bad coding styles. Using `bool operator==(element_t, std::uint32_t)` is a temporary solution and causes confusion to readers including the future author himself.
I would rather keep my code "clean":
1. Make projection (loss of information) explicit, since an object is-not-equal-to its member (in information theory sense);
I think you're missing the point of the article. There are infinite legitimate use-cases which fail to compile because of the burden of satisfying `equality_comparable_with`. Transparent lookups in unordered containers for example, treat std::string and std::string_view more ergonomically than ranges even though its an older C++ feature.
This article is _not about ranges_. It is about the bureaucratic process of the standardization committee breaking down and failing to deliver the highest levels of quality for big-ticket features. This is explained at the end.
Again, redefining equality to completely ignore `name`. So `User{"Bob", 10} == User{"Alice", 10}`. Boo!
> The same issue appears with fundamental types and standard library types: [...]
This is a much more compelling example. Too bad that [it compiles and works](https://gcc.godbolt.org/z/dr3WrYY5G), despite you claiming otherwise.
**Testing your code snippets is the bare minimum before writing a blog post.**
There are so many valid things to critique about ranges (e.g. compile time bloat, poor debuggability, poor debug performance) and yet you pick (1) terrible premises and (2) incorrect examples?
"The Problem" indeed exists in real-word code, but imo it's caused by bad coding styles. Using `bool operator==(element_t, std::uint32_t)` is a temporary solution and causes confusion to readers including the future author himself.
I would rather keep my code "clean":
1. Make projection (loss of information) explicit, since an object is-not-equal-to its member (in information theory sense);
2. Avoid comparing values of different types.
```
std::ranges::find(elements, what_to_find, &element_t::member);
std::ranges::find(ints, static_cast<int>(a_long)); // value truncated, dangerous
std::ranges::find(ints | std::transform(turn_int_to_long), a_long); // value preserved, safe
std::ranges::find(longs, static_cast<long>(a_int)); // elements preserved, safe
std::ranges::find(longs | std::transform(turn_long_to_int), a_int); // elements truncated, dangerous
```
I think you're missing the point of the article. There are infinite legitimate use-cases which fail to compile because of the burden of satisfying `equality_comparable_with`. Transparent lookups in unordered containers for example, treat std::string and std::string_view more ergonomically than ranges even though its an older C++ feature.
This article is _not about ranges_. It is about the bureaucratic process of the standardization committee breaking down and failing to deliver the highest levels of quality for big-ticket features. This is explained at the end.
Poor article.
> The Packet type provides symmetric operator== overloads for comparison with std::uint32_t. This is a natural design [...]
Bad premise and bad design. Equality on `Packet` should *naturally* compare the value/contents of the packet, not one arbitrary member.
I would never let this code get through review.
auto it = std::ranges::find_if(rx_buffer,
[](Packet const& p) { return p == 1002; });
Yep -- did you seriously write this and felt like *"yeah, `p == 1002` seems like reasonable code"*?
struct User {
std::string name;
int id;
friend bool operator==(User const& u, int user_id) noexcept {
return u.id == user_id;
}
};
Again, redefining equality to completely ignore `name`. So `User{"Bob", 10} == User{"Alice", 10}`. Boo!
> The same issue appears with fundamental types and standard library types: [...]
This is a much more compelling example. Too bad that [it compiles and works](https://gcc.godbolt.org/z/dr3WrYY5G), despite you claiming otherwise.
**Testing your code snippets is the bare minimum before writing a blog post.**
There are so many valid things to critique about ranges (e.g. compile time bloat, poor debuggability, poor debug performance) and yet you pick (1) terrible premises and (2) incorrect examples?