There are two things you missed in the interface of map
(and the like):
insert(value_type)
returns a std::pair<iterator, bool>
, the .first
member points to the element with the key you tried to insert and the .second
member indicates whether it is actually the element you tried to insert or another that previously was in the container.
insert(iterator, value_type)
allows you to give a hint as to where insert
The latter is not necessarily useful in your situation though.
typedef std::map<int,X> Map;
// insert and check
std::pair<Map::iterator, bool> const result =
map.insert(std::make_pair(5, x)); // O(log N)
if (not result.second)
{
result->first.second = x; // O(1)
// OR
using std::swap;
swap(result->first.second, x);
}
If you type does not support assignment and there is no swap, however, you need to bite the bullet:
// locate and insert
Map::iterator position = map.lower_bound(5); // O(log N)
if (position != map.end() and position->first == 5)
{
position = map.erase(position); // O(1)
}
map.insert(position, std::make_pair(5, x)); // O(log N) if rebalancing
In C++11, the insert
methods are doubled:
insert(value_type const&)
// insertion by copy
insert(P&&)
// insertion by move
and with perfect forwarding we get the new emplace
method. Similar to insert, but which construct the element in place by forwarding the arguments to its constructor. How it differentiate arguments for the key and value is a mystery to me though.