
On Thu, 19 Dec 2024 at 17:50, Ivan Matek
On Thu, Dec 19, 2024 at 6:26 PM Neil Groves via Boost < boost@lists.boost.org> wrote:
One aspect that strikes me about all of our alternatives is that none of them work particularly well when we are using multi_ associative containers.
If I understand your comment correctly: "correct" return type is a std::ranges::subrange, equal_range returns std::pair so you need some helper to "rangify" that pair. (this example uses biset so you can ignore .get<1>).
EmployeeSet ems{{1, "Alice"}, {2, "Bob"}, {3, "Chad"}, {4, "Alice"}};
for (const Employee& employee : ems.get<1>().equal_range("Alice") | rangify) {
std::print("{} {}\n", employee.id, employee.name);
}
Yes exactly that. It's not exactly equal_range, in the same way that it wasn't quite "find" either as they both return the mapped_type not the dereferenced iterator value. I intend to build upon this idea with a wrapper type around the equal_mapped_range (better name required!) function with a result type that can perform the range approaches nicely e.g. like the optional "map" member function. However there are cases where the optional type has some nice things that the typical range does not. I'm looking into this because I think there may be powerful idioms for empty_range -> default_value , for illegal iterator dereference converted to policy-based return. While it would be easy to just fix find, what about std::ranges::find_if etc? I appreciate this wouldn't have the mapped_value angle, but the default if the value doesn't exist is the same problem. I believe reusable abstractions can be built that will help build the specific use-case solution, but also improve our set of tools available more generally. I need to do more keyboard bashing and less flapping of my gums (keys). I may be the only person excited, but I am genuinely enthused about this direction. Neil