Reputation: 1244
Consider following snippet:
MapT map;
map["A"] = 1;
map["B"] = 2;
map["C"] = 3;
map["D"] = 4;
map["E"] = 5;
MapT mapSecond;
mapSecond["A"] = 10;
mapSecond["B"] = 20;
mapSecond["C"] = 30;
mapSecond["X"] = 4;
mapSecond["Y"] = 5;
MapT::const_iterator itSecond = mapSecond.begin();
MapT::iterator it = map.begin();
for (; itSecond != mapSecond.end(); ++itSecond)
{
std::pair<MapT::iterator, bool> pair = map.insert(std::make_pair(itSecond->first, itSecond->second));
if (!pair.second)
{
pair.first->second = itSecond->second;
}
}
for (; it != map.end(); ++it)
{
std::cout << it->first << " " << it->second << std::endl;
}
I assume using the returned iterator from insert is the most efficient version.
However at first, I did just thought assigning the iterators only works fine (note I am not dereferencing the iterator anymore here).
1.)
// assigning the dereferenced iterator (i.e.: the underlying std::pair)
// resulting in no match for binary '=' operator for const std::string
*pair->first = *itsecond;
I know its obsolete as I already matched the key and only care about the value. This error occurs only because of the key being a const std::string If I am not completely out of my mind :D
2.)
// assigning the iterator itself
// does not compile as long as itSecond is of type const_iterator ?
// does nothing in case itSecond is of type iterator
pair.first = itSecond;
This is the thing I actually don't understand. How is the assignment of an iterator in a std::map supposed to behave? Although I do program C++ for a few years already, I never encountered a scenario where I did so for any container. I have not found a lot of information about assigning iterators in general during a bit of research.
And finally would there be an even more elegant way of doing what I want to achieve (using C++11 features, maybe C++14)?
Upvotes: 0
Views: 13222
Reputation: 409166
Why make it so complicated? Why not simply
map[itSecond->first] = itSecond->second;
If they key exists, the data will be changed. If the key doesn't exist, then the pair will be inserted.
Also don't forget that the value_type
of std::map
(and std::unordered_map
for that matter) is std::pair<const Key, T>
.
As the key is constant you can't simply assign or copy iterators, you can only assign or copy the value.
Upvotes: 9
Reputation: 3955
To answer the first question
How is the assignment of an iterator in a std::map supposed to behave?
:
MapT::Iterator
satisfies BidirectionalIterator
, which satisfies ForwardIterator
, which satisfies Iterator
.
An Iterator
is CopyAssignable
.
So the assignment t = v;
will make
- The value of
t
is equivalent to the value ofv
.- The value of
v
is unchanged.
In this case substitute t
with pair.first
, and v
with itSecond
. Note that the map is not changed with this.
(imagine pointers. Of course assigning pointers won't modify contents they point to)
Upvotes: 1
Reputation: 1255
Assuming C++17 is okay, you can use merge: https://en.cppreference.com/w/cpp/container/map/merge
But it doesn't overwrite the data, so you'd have to merge the first into the second.
Upvotes: 0