Reputation: 16705
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::transform
does not change the map by replacing values with the existing key, so I have this:
{
{1, boost::none},
{3, boost::none},
{5, boost::none},
{7, boost::none},
{9, boost::none},
}
Is it possible to make it work as following simple range-based for?
for (const auto &i : vector) {
map[i] = boost::optional<my_type>(val));
}
P.S. I know how the std::inserter
works and std::map::insert
too, just curious how can I change the transform in order to change values.
Upvotes: 4
Views: 1751
Reputation: 55887
Not with inserter
, since insert
inserts elements only and only if there is no element in map
.
There will be insert_or_assign in C++17.
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);
}
Upvotes: 5