If transparent hash and key comparison functions are used with std::unordered_map
, its find
has since C++20 had an overload that allows calling the function without constructing an instance of the key. However, try_emplace
does not currently have such an overload, so my understanding is that an instance of Key
is always constructed when the function is called.
Is there any way to replicate this behaviour of find
in a function that works somewhat like try_emplace
or operator[]
? In other words, I would like to retrieve the old value if one exists, or emplace a new value. I could just use a combination of find
and emplace
but I’m guessing that emplace
does some unnecessary work in this case. If I had first determined a candidate location, I could pass it to emplace_hint
(like with lower_bound
when using std::map
), but I don’t know how to get a suitable iterator when using std::unordered_map
.
The most efficient way to emulate the try_emplace()
member function in the std::unordered_map
container for heterogeneous lookup involves a combination of both the find()
and emplace()
member functions.
Example:
template <typename K, typename ...Args>
std::pair<iterator, bool> try_emplace(K&& k, Args&& ...args)
{
std::pair<iterator, bool> p{this->find(k), false};
if(p.first != this->end())
p = this->emplace(std::forward<K>(k), std::forward<Args>(args)...);
return p;
}
Indeed, the use of the emplace_hint()
member function to exploit the already-existing iterator does not determine any performance improvement, since all the major implementations (MSVC, libc++, libstdc++) do not consider the "hint".