std::map::try_emplace() seems very convenient and efficient but it's only available in C++17. Is it possible to re-implement it in C++11?
template <class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); std::map::try_emplace() seems very convenient and efficient but it's only available in C++17. Is it possible to re-implement it in C++11?
template <class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); For an ordered map, you can get close to the behaviour with lower_bound:
template <class M, class... Args> std::pair<typename M::iterator, bool> try_emplace_m(M& m, const typename M::key_type& k, Args&&... args) { auto it = m.lower_bound(k); if (it == m.end() || m.key_comp()(k, it->first)) { return {m.emplace_hint( it, std::piecewise_construct, std::forward_as_tuple(k), std::forward_as_tuple(std::forward<Args>(args)...)), true}; } return {it, false}; } For an unordered map, you can't use lower_bound. You can replace it with find, and the test with key_eq(), to get a functional version, which will perform a repeated lookup in the case of an insertion, though. Sp speaking purely in terms of algorithmic complexity this new member function pulls more weight in the unordered case, which users cannot currently implement using only the public API. But the added convenience applies equally to both cases.
lower_bound operation is already comparing keys.try_emplace with hint for map. Current libc++ ignores user-provided hint. OTOH libstdc++ implement it by replacing lower_bound with internal interface. I have written some related interface to ease such. It is named search_map here, but can be also used on other custom associative containers. I have implemented (more compact than the internal impl in libstdc++) but haven't release the overloading with hint parameter. I will commit it days (less than a week) later hopefully.Hmmm... Simply search for the value before?
auto it = map.find(k); if (it == map.end()){ //value does not exist auto newIt = map.emplace({std::move(k),std::forward<Args>(args)...}); } try_emplace since it will still create an intermediary std::pair instead of truly constructing the element in place.