I have a map in a multithreaded app mapping a class called uuid to pointer.
What I want to know if an insert operation succeeded for failed.
e.g.
_mymap.insert(hint, MyMap::value_type(entry.uuid, itemptr));
Does it throw an exception or something if it fails?
In fact the insert method which takes a hint parameter does not return whether the insert succeeded or not. One way to check if insert actually happened would be to check the size of the map before and after insertion. If it is the same, then insert has failed (i.e. the key was already present). I know it sounds ugly, but that's the most efficient way I could come up with. In fact I believe that there is no compelling reason that the insert with a hint should not return a pair (including the bool) just like the regular non-hint insert does. But once it has been specified in an older standard, it is very hard to change, since it is a breaking change, which the C++ community mostly resents.
Original (wrong) answer
See this link
... returns a pair, with its member pair::first
set to an iterator pointing to either the newly inserted element or to the element that already had its same value in the map. The pair::second
element in the pair is set to true if a new element was inserted or false if an element with the same value existed.
The link also contains an example
For example:
if(mp.insert(make_pair(key, value)).second == false)
{
cout << "Insertion failed. Key was present"
}
typedef std::map<std::string, int> map;
map m;
std::pair<map::iterator,bool> result = m.insert(std::make_pair("hi", 42));
result.second contains what you want
It depends what you mean by failed or succeeded.
std::map::insert succeeds when it inserts the new element or returns an iterator to an already existing element.
std::map::insert fails if there is not enough memory to insert a new element and throws std::bad_alloc.
Yes, it would throw one of the exceptions used in the STL, e.g. when out of memory. That is in case of failure.
Or were you also interested in knowing whether the element was already contained in the instance?
The first insert member function
returns a pair whose bool component
returns true if an insertion was made
and false if the map already contained
an element whose key had an equivalent
value in the ordering, and whose
iterator component returns the address
where a new element was inserted or
where the element was already located.
To access the iterator component of a
pair pr returned by this member
function, use pr.first, and to
dereference it, use *(pr.first). To
access the bool component of a pair pr
returned by this member function, use
pr.second.
The second insert member function, the
hint version, returns an iterator that
points to the position where the new
element was inserted into the map.
Source: http://msdn.microsoft.com/en-us/library/81ac0zkz(v=vs.80).aspx
It is also possible to know if a pair was inserted or found in a map after insertion with hint (much faster).
Insert with hint method another pair of the same first, and of a second that you are sure is not in the map ( like (size_t) -1 for a map of sizes for instance ?). If the iterator returned has this impossible value, it has been newly inserted, if not it was found in the map. The iterator returned may then be changed.
Example : to insert pairs p (2,4) and p (6, 5) in the map m ((0, 1), (2, 3), (4, 5)).
int main (int argc, char* argv []) {
std::pair<size_t, size_t> tmp [3] = {
std::pair<size_t, size_t> (0, 1),
std::pair<size_t, size_t> (2, 3),
std::pair<size_t, size_t> (4, 5)
};
std::map<size_t, size_t> m ((std::pair<size_t, size_t>*) tmp, (std::pair<size_t, size_t>*) &tmp [3]);
std::cout << "initial map == ";
std::for_each (m.begin (), m.end (), [] (const std::pair<size_t, size_t>& p) {
std::cout << p.first << "->" << p.second << " ";
});
std::cout << std::endl;
std::cout << std::endl;
{
//insertion of a pair of first already in map
std::cout << "insertion of pair 1 == std::pair<size_t, size_t> (2, 4) from second iterator" << std::endl;
std::map<size_t, size_t>::iterator ihint (m.begin ()), k (ihint); ++ihint;
std::pair<size_t, size_t> pfoo (2, (size_t) -1);
k = m.insert (ihint, pfoo);
if (k->second == (size_t) -1) {
std::cout << "\tthe pair was inserted" << std::endl;
k->second = 4;
}
else {
std::cout << "\ta pair with such a first was in the map" << std::endl;
}
}
std::cout << "m after insertion of pair 1 == ";
std::for_each (m.begin (), m.end (), [] (const std::pair<size_t, size_t>& p) {
std::cout << p.first << "->" << p.second << " ";
});
std::cout << std::endl;
std::cout << std::endl;
{
//insertion of a pair of first not in map
std::cout << "insertion of pair 2 == std::pair<size_t, size_t> (6, 5) from third iterator" << std::endl;
std::map<size_t, size_t>::iterator ihint (m.begin ()), k (ihint); ++ihint; ++ihint;
std::pair<size_t, size_t> pfoo (6, (size_t) -1);
k = m.insert (ihint, pfoo);
if (k->second == (size_t) -1) {
std::cout << "\tthe pair was inserted" << std::endl;
k->second = 5;
}
else {
std::cout << "\ta pair with such a first in the map" << std::endl;
}
}
std::cout << "m after insertion of pair 2 == ";
std::for_each (m.begin (), m.end (), [] (const std::pair<size_t, size_t>& p) {
std::cout << p.first << "->" << p.second << " ";
});
std::cout << std::endl;
}
outputs :
initial map == 0->1 2->3 4->5
insertion of pair 1 == std::pair (2, 4) from second iterator
a pair with such a first was in the map
m after insertion of pair 1 == 0->1 2->3 4->5
insertion of pair 2 == std::pair (6, 5) from third iterator
the pair was inserted
m after insertion of pair 2 == 0->1 2->3 4->5 6->5