Std :: map replaces existing elements with conversion

I have a code:

std::vector<int> vector = {1, 3, 5, 7, 9};
using my_type = std::pair<int, int>;
std::map<int, boost::optional<my_type>> map;
for (const auto &i : vector) {
    map[i] = boost::none;
}
const my_type val = {1, 5};
std::transform(vector.cbegin(),
               vector.cend(),
               std::inserter(map, map.end()),
               [&val](const int &i) {
                   return std::make_pair(i, boost::optional<my_type>(val));
});

Everything works fine, but std::transformdoes not change the map, replacing the values ​​with an existing key, so I have the following:

{ 
    {1, boost::none},
    {3, boost::none},
    {5, boost::none},
    {7, boost::none},
    {9, boost::none},
}

Is it possible to make it work as the next simple range?

for (const auto &i : vector) {
    map[i] = boost::optional<my_type>(val));
}

PS I know how it works std::inserterand std::map::insert, just curious, how can I change the transformation to change the values.

+4
source share
1 answer

Not with inserter, since it insertonly inserts elements and only if there is mapno element. In C ++ 17 there will be insert_or_assign .

template<typename Map>
struct map_insert_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
   map_insert_iterator(Map& m) : map(m)
   {
   }
   map_insert_iterator<Map>& operator = (const typename Map::value_type& value)
   {
      map.insert_or_assign(value.first, value.second);
      return *this;
   }
   map_insert_iterator<Map>& operator * () { return *this; }
   map_insert_iterator<Map>& operator ++ () { return *this; }
   map_insert_iterator<Map>& operator ++ (int) { return *this; }
private:
   Map& map;
};

template<typename Map>
map_insert_iterator<Map> map_inserter(Map& m)
{
   return map_insert_iterator<Map>(m);
}

Live

+5
source

Source: https://habr.com/ru/post/1624225/


All Articles