c++stl

Is there a function can modify map's value and return the iterator?


What I want is to insert a pair<key, value> into the map (create it if not existed, modify it otherwise), and got the value's pointer, to let others use.

here is a demo code:

#include <map>
using namespace std;
std::map<int, int> a = {{1, 1}};
int* set_and_return_value() {
  // option 1: a[1] = 2; return &(a[1]); i think it's ugly
  const auto [it, ok] = a.emplace(1, 2); 
  return &(it->second);
  // emplace is good, but it won't modify the existed key's value
}

So, is there a function, can return the iterator after real insert the pair?


Solution

  • Assigning via iterator does not invalidate the iterator, you can use that and the return value of emplace to conditionally assign if the insertion failed:

    #include <map>
    
    using namespace std;
    std::map<int, int> a = {{1, 1}};
    auto set_and_return_it() {
        const auto [it, inserted] = a.emplace(1, 2);
        if (!inserted) {
            it->second = 2;
        }
        return it;
    }
    

    If you want it more generic, use try_emplace to avoid constructing 2 twice.

    template<typename K, typename T>
    auto set_and_return_it(K&& key, T&& value) {
        const auto [it, inserted] = a.try_emplace(std::forward<K>(key), std::forward<T>(value));
        if (!inserted) {
            it->second = std::forward<T>(value);
        }
        return it;
    }