
Christian Mazakas wrote:
I'm with Andrey, I think the iterator API *is* the useful API. Typically, when I find something in a map, I'll either erase or do something else where reusing the iterator is a key part of everything.
My whole thing was about what users actually wanted vs all the costs of everything else.
What this user has always wanted is to not have to write this: auto it = map.find( key ); if( it != map.end() ) { // do something with it->second } That's why I'm always defining a helper function `lookup` that returns a pointer, which allows me to write this instead: if( auto p = lookup( map, key ) ) { // do something with *p } If there's a built-in way to obtain an optional<mapped_type&> instead of an iterator, I can use that instead of `lookup`, without changing the syntax. Although it strikes me that it should probably be named `try_at` instead of `try_find`. `find` is already a try-ing member function, because it doesn't fail, whereas `at` both returns the correct reference type, and can fail. Of course `try_at` by convention ought to return boost::system::result or std::expected instead of an optional, but that's another story. Interestingly, and maybe relevant for this discussion, `at` was added to associative containers even though it could have been made a free function instead.