Why unordered_map::equal_range upper_bound returns end if a key is less than first map element - c++

I've noticed that unordered_map::equal_range upper_bound (first) returns end if passed key is less than map's first one
#include <iostream>
#include <map>
#include <tr1/unordered_map>
using namespace std;
int main ()
{
{
std::map<char,int> mymap;
mymap['c'] = 60;
std::map<char,int>::iterator itup = mymap.equal_range('a').first;
std::cout << "map::itup " << itup->first << std::endl;
}
{
tr1::unordered_map<char, int> mymap;
mymap['c'] = 60;
mymap['d'] = 70;
tr1::unordered_map<char, int>::iterator itlo = mymap.equal_range('a').first;
tr1::unordered_map<char, int>::iterator itup = mymap.equal_range('a').second;
cout << "unordered_map::itup " << (itup == mymap.end() ? "END" : "NOT END") << std::endl;
cout << "unordered_map::itlo " << (itlo == mymap.end() ? "END" : "NOT END") << std::endl;
}
return 0;
}
Output is:
map::itup c
unordered_map::itup END
unordered_map::itlo END
Note that the behavior is different for map and unordered_map - any reasons for that or is this a problem in unordered_map?
Thanks,
Alexander

This happens because an unordered_map is, not too surprisingly, unordered.
See §22.2.7 [unord.req], Table 70, regarding the requirements on equal_range:
Returns: A range containing all elements with keys equivalent to k.
Returns make_­pair(b.end(), b.end()) if no such elements exist.
This is different from the requirements on an ordered associative container, like std::map, where equal_range is defined in terms of lower_bound and upper_bound.
std::unordered_map doesn't have lower_bound and upper_bound, for obvious reasons.

You asked for a range consisting of all elements in your unordered_map whose key is 'a'. Your unordered map contains no such elements. So, the range is empty.
The same is true of the map case. However, the way in which this condition is signified differs by container (although not really; keep reading). The containers std::map and std::unordered_map are not the same thing (hence they have different names). The former is ordered, whereas the latter is not, so for logical implementation reasons it works slightly differently:
unordered_map
Return value
std::pair containing a pair of iterators defining the wanted range. If there are no such elements, past-the-end (see end()) iterators are returned as both elements of the pair.
map
Return value
std::pair containing a pair of iterators defining the wanted range: the first pointing to the first element that is not less than key and the second pointing to the first element greater than key.
If there are no elements not less than key, past-the-end (see end()) iterator is returned as the first element. Similarly if there are no elements greater than key, past-the-end iterator is returned as the second element.)
This difference does not matter. In either case you should simply iterate (first, second] to examine the elements (if any exist) in your range, as you would with any iterator range.
In your code, you didn't examine both parts of the pair returned in your map case. If you do then you'll find that first == second (again, signifiying an empty range).
Your map code effectively dereferences the "past-the-end" iterator of the returned range.
#include <iostream>
#include <map>
#include <unordered_map>
using namespace std;
int main ()
{
{
std::map<char,int> mymap;
mymap['c'] = 60;
std::map<char, int>::iterator itlo = mymap.equal_range('a').first;
std::map<char, int>::iterator itup = mymap.equal_range('a').second;
// This compares each range extent to the map's end, which is not really useful
cout << "map::itup " << (itup == mymap.end() ? "END" : "NOT END") << '\n';
cout << "map::itlo " << (itlo == mymap.end() ? "END" : "NOT END") << '\n';
// This examines the range itself
cout << "map range empty: " << (itlo == itup ? "YES" : "NO") << '\n';
cout << "map range size: " << std::distance(itlo, itup) << '\n';
}
{
std::unordered_map<char, int> mymap;
mymap['c'] = 60;
mymap['d'] = 70;
std::unordered_map<char, int>::iterator itlo = mymap.equal_range('a').first;
std::unordered_map<char, int>::iterator itup = mymap.equal_range('a').second;
// This compares each range extent to the map's end, which is not really useful
cout << "unordered_map::itup " << (itup == mymap.end() ? "END" : "NOT END") << std::endl;
cout << "unordered_map::itlo " << (itlo == mymap.end() ? "END" : "NOT END") << std::endl;
// This examines the range itself
cout << "unordered_map range empty: " << (itlo == itup ? "YES" : "NO") << '\n';
cout << "unordered_map range size: " << std::distance(itlo, itup) << '\n';
}
}
// Output:
//
// map::itup NOT END
// map::itlo NOT END
// map range empty: YES
// map range size: 0
// unordered_map::itup END
// unordered_map::itlo END
// unordered_map range empty: YES
// unordered_map range size: 0
(live demo)

Related

STL MAP should use find() or [n] identifier to find element in map?

I am confused which is more efficient?
As we can access map directly, why do we need to use find?
I just need to know which way is more efficient.
#include <iostream>
#include <map>
using namespace std;
int main ()
{
map<char,int> mymap;
map<char,int>::iterator it;
mymap['a']=50;
mymap['b']=100;
mymap['c']=150;
mymap['d']=200;
//one way
it=mymap.find('b');
cout << (*it).second <<endl;
//another way
cout << mymap['b'] <<endl;
return 0;
}
thanks in advance! :)
Using find means that you don't inadvertently create a new element in the map if the key doesn't exist, and -- more importantly -- this means that you can use find to look up an element if all you have is a constant reference to the map.
That of course means that you should check the return value of find. Typically it goes like this:
void somewhere(const std::map<K, T> & mymap, K const & key)
{
auto it = mymap.find(key);
if (it == mymap.end()) { /* not found! */ }
else { do_something_with(it->second); }
}
As we can access map directly, why do we need to use find?
Because map<>::operator[] is sometimes nasty. If an element doesn't exist then:
it inserts it
value initialize it
returns reference of value
Thus it always returns a valid reference of value, even if a key din't exist previously. This behavior is not intended many times.
On the other hand map<>::find() is safer; because it returns end(), if a value doesn't exit. Another advantage of find() is that it returns an iterator which contains references to key (first) and value(second) both.
The [] operator in map is not constant it is logarithmic. Most of the books stress on this fact and point out it is a bit misleading. So both find and [] operator are with the same complexity.
Please note that the [] operator will create the entry even if it does not exist while find will return end() in that case.
This code and doc is picked from cplusplus.com
// accessing mapped values
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main ()
{
map<char,string> mymap;
mymap['a']="an element";
mymap['b']="another element";
mymap['c']=mymap['b'];
cout << "mymap['a'] is " << mymap['a'] << endl;
cout << "mymap['b'] is " << mymap['b'] << endl;
cout << "mymap['c'] is " << mymap['c'] << endl;
cout << "mymap['d'] is " << mymap['d'] << endl;
cout << "mymap now contains " << (int) mymap.size() << " elements." << endl;
return 0;
}
OP:
mymap['a'] is an element
mymap['b'] is another element
mymap['c'] is another element
mymap['d'] is
mymap now contains 4 elements.
Notice how the last access (to element 'd') inserts a new element in the map with that key and initialized to its default value (an empty string) even though it is accessed only to retrieve its value. Member function map::find does not produce this effect.

iterating over an STL container using element keys

I need some help with choosing an efficient algorithm to put elements from a vector into presorted buckets - or ideally output iterator ranges (as they are efficient I think). The example below is totally contrived, but the idea is that a an element's key is used to determine the output bucket. I'm not asking how to sort in order as that is a very simple matter of simply calling (which works and reorders the elements according to the key)
std::sort(testVec.begin(), testVec.end(), comparator);
I put a live example on coliru, where it is very easy to modify and fix (well not that easy or I wouldn't be asking the question). I could also go through the elements in this sorted list and while the key value is the same, append it into a new bucket, but I am looking for something more STL like in nature, and right now the above smells like a bit of a last resort hack, also the final solution needs to be efficient as the testVec is potentially large and the objects are also big in size. I would prefer not to modify the testvec - so it should be immutable.
Ideally I am looking for some sort of construct that spits out range iterators or something equally efficient. The actual objects are large so passing references or moving them is really the only option - my actual objects (the equivalent to MyStr) are movable. Something sort of foreach key, apply key predicate or something which I cannot figure out is what I am looking for. I hard coded the 3 buckets below just to show what I need to be able to attain - this is totally a hack.
Thanks in advance for any help with this problem
#include <string>
#include <iostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <algorithm>
struct MyStr
{
int key;
std::string strval;
MyStr(int key, const std::string& rStrVal)
: key(key)
, strval(rStrVal)
{}
// let stream operators be friend functions instead of members!
inline friend std::ostream& operator << (std::ostream& os, const MyStr& val) {
os << "key[" << val.key << "], strval['" << val.strval << "']";
return os;
}
bool operator < (const MyStr& str) const {
return (key > str.key);
}
};
int main()
{
std::vector <MyStr> testVec = {
MyStr(4, "key 4"),
MyStr(3, "key 3"),
MyStr(3, "key 3"),
MyStr(2, "key 2"),
MyStr(2, "key 2"),
MyStr(2, "key 2")
};
//auto comparator = [](const MyStr& lhs, const MyStr& rhs) {
// return lhs.key < rhs.key;
//};
std::vector <MyStr> foursBucket;
std::vector <MyStr> threesBucket;
std::vector <MyStr> twosBucket;
auto ostriter = std::ostream_iterator<MyStr>(std::cout, ",");
std::for_each(testVec.begin(), testVec.end(),
[&](const MyStr& next){
switch (next.key) {
case 4:
foursBucket.push_back(next);
break;
case 3:
threesBucket.push_back(next);
break;
case 2:
twosBucket.push_back(next);
break;
}
});
std::cout << "Elements with Key Value 2" << std::endl;
std::copy(twosBucket.begin(), twosBucket.end(), ostriter);
std::cout << std::endl;
std::cout << "Elements with Key Value 3" << std::endl;
std::copy(threesBucket.begin(), threesBucket.end(), ostriter);
std::cout << std::endl;
std::cout << "Elements with Key Value 4" << std::endl;
std::copy(foursBucket.begin(), foursBucket.end(), ostriter);
std::cout << std::endl;
}
produces the following output
Elements with Key Value 2
key[2], strval['key 2'],key[2], strval['key 2'],key[2], strval['key 2'],
Elements with Key Value 3
key[3], strval['key 3'],key[3], strval['key 3'],
Elements with Key Value 4
key[4], strval['key 4'],
As you can see the structure is very simple and I've shown how I can currently sort the objects using a predicate but I do not know which of the plethora of algorithms to choose from to efficiently iterate over
You're looking for an unordered_multimap. It is an unordered associative container that'll place the key-value pairs into buckets depending on the hash value of the key (int in the following example).
std::unordered_multimap<int, std::string>
mymap{{4, "key 4"},
{3, "key 3"},
{3, "key 3"},
{2, "key 2"},
{2, "key 2"},
{2, "key 2"},
};
for(auto const& kv : mymap) {
std::cout << "key: " << kv.first << " value: " << kv.second << '\n';
}
Output:
key: 2 value: key 2
key: 2 value: key 2
key: 2 value: key 2
key: 3 value: key 3
key: 3 value: key 3
key: 4 value: key 4
Live demo
In the comment below you clarified that you receive a vector<MyStr> input, and the container type cannot be changed. In that case, use std::equal_range to find all the elements containing a particular key.
// comparator for equal_range
struct comp
{
bool operator()(int key, MyStr const& m) const { return m.key < key; }
bool operator()(MyStr const& m, int key) const { return key < m.key; }
};
// sort the vevctor
std::sort(testVec.begin(), testVec.end());
// search for all elements with key=2
auto range = std::equal_range(testVec.begin(), testVec.end(), 2, comp());
for(auto it = range.first; it != range.second; ++it) {
std::cout << "key: " << it->key << " value: " << it->strval << '\n';
}
Output:
key: 2 value: key 2
key: 2 value: key 2
key: 2 value: key 2
Live demo
To iterate over each unique key, the easiest way is to use std::unique_copy to create a new container that holds only elements that have unique keys. Then iterate over this container and use equal_range on each key.
bool operator==(MyStr const& m1, MyStr const& m2) { return m1.key == m2.key; }
// sort the vevctor
std::sort(testVec.begin(), testVec.end());
std::vector<MyStr> unique_keys;
std::unique_copy(testVec.begin(), testVec.end(), std::back_inserter(unique_keys));
for(auto const& u : unique_keys) {
std::cout << "Searching for key: " << u.key << '\n';
auto range = std::equal_range(testVec.begin(), testVec.end(), u.key, comp());
for(auto it = range.first; it != range.second; ++it) {
std::cout << "key: " << it->key << " value: " << it->strval << '\n';
}
}
Live demo
If the elements are expensive to copy, and you'd rather avoid having to create a new container holding unique elements, you could create your own output iterator that mimics std::back_insert_iterator. Its operator= implementation will take a MyStr const& argument, but push_back only the key from the argument into the unique key container, which would be vector<int> in that case.
Another approach (that I'm not certain will work) that you can use to avoid modifying the input range, and avoid copying the elements to a new range, is to create vector<MyStr *>, where each element points to the corresponding element in the original range. Then repeat all the steps above, except, instead of passing vector::iterators to the algorithms, use boost::indirect_iterator. This iterator will apply an extra level of dereferencing to the pointers in your container, and the algorithms should then work as if they were operating on vector<MyStr> instead.

Inserting to std::list using reverse iterator changes the value of the original reverse iterator

Have searched the net a lot, but couldn't find the answer to the issue.
I am inserting a value to an std::list using its reverse_iterator. While the insertion occurs at the appropriate position as expected, what I noticed is that the value of the original reverse_iterator used for insertion changes. Also the value of a completely unrelated reverse_iterator too changes. I have been able to reproduce this in a simple example
#include <iostream>
#include <list>
#include <string>
int main()
{
// Creating a list of values 1, 2, 4, 5
std::list<int> myList;
myList.push_back(1);
myList.push_back(2);
myList.push_back(4);
myList.push_back(5);
// Changing it to 1, 2, 3, 4, 5 by inserting 3
std::list<int>::reverse_iterator revIter = myList.rbegin();
while(2 != *revIter)
{
std::cout << *revIter << "\t";
++revIter;
}
std::cout << "\n" << "Reverse iterator now points to " << *revIter;
// Creating a copy of the reverse Iter before inserting.
std::list<int>::reverse_iterator newRevIter = revIter;
myList.insert(revIter.base(), 3);
// Checking the values of revIter and newRevIter
std::cout << "\n" << "Reverse Iterator now points to " << *revIter; // UNEXPECTED RESULT HERE
std::cout << "\n" << "New Reverse Iterator now points to " << *newRevIter; // UNEXPRECTED RESULT HERE
std::cout << "\n" << "Printing final list:" << "\n";
for(std::list<int>::iterator iter = myList.begin(); myList.end() != iter; ++iter)
{
std::cout << *iter << "\t"; // Results are fine
}
return 0;
}
RESULT
5 4
Reverse iterator now points to 2
Reverse iterator now points to 3
New Reverse iterator now points to 3
Printing final list:
1 2 3 4 5
Is this expected behaviour. If so how can reverse iterator be used to insert items to a list (Or is it useless in this regard)?
I would avoid using reverse iterators (in general, and in particular for anything other than a sequential transversal). Forward and reverse iterators work differently, in the case of a forward iterator into a list, the iterator tracks the node that you access through operator*, but in the reverse case the iterator tracks the next element in the list. The act of dereferencing a reverse iterator obtains the predecessor of the node referred by the iterator and extracts the value from that. Graphically (f is a forward iterator, r is a reverse iterator)
f
1 2 4
r
Both the forward iterator f and the reverse iterator r will yield 2 when dereferenced, but the node they track is different. When you insert using r you insert between 2 and 4, but the underlying iterator is left pointing to the node holding the 4:
f
1 2 3 4
r
Now if you dereference r, the same process as above applies. The predecessor of the current node is obtained, and the value printed, except that now the predecessor of 4 is 3 and that is what you get.
Is this expected behaviour. If so how can reverse iterator be used to insert items to a list (Or is it useless in this regard)?
Yes, this is expected behavior. How can a reverse iterator be used to insert items to a list? Understanding how it works.
The invariant after insertion is the std::reverse_iterator<>::base(), not the std::reverse_iterator<> itself. But, base() does target the previous elements compared to reverse_iterator:
http://en.cppreference.com/w/cpp/iterator/reverse_iterator
What's bother me a bit is that when I had std::distance to the begin() (or rend().base() ):
std::cout << "\n"
<< "Reverse Iterator now points to "
<< *revIter << "-" << *(revIter.base())<< "-"
<< std::distance(revIter.base(), myList.rend().base());
I have:
Reverse iterator now points to 2-4-3
Reverse Iterator now points to 3-4-3
Or I expect the second one to be "3-4-4" as the element is inserted prior to the base()...

Confused use of c++ STL iterator

While I use iterator like this ,
//include header files
using namespace std;
int main()
{
map<int,int> intIntMap;
map<int,int>::iterator pos;
pos = intIntMap.begin();
intIntMap[0] = 1;
intIntMap[3] = 5;
intIntMap[4] = 9;
intIntMap[5] = 5;
//遍历
cout << (*pos).first << endl;
while( pos != intIntMap.end() )
{
cout << pos->first << " <---> " << pos->second << endl;
pos++;
}
}
The output is 4;
But while I use iterator like this:
//include header file
using namespace std;
int main()
{
map<int,int> intIntMap;
map<int,int>::iterator pos;
intIntMap[0] = 1;
intIntMap[3] = 5;
intIntMap[4] = 9;
intIntMap[5] = 5;
//遍历
pos = intIntMap.begin();
cout << (*pos).first << endl;
while( pos != intIntMap.end() )
{
cout << pos->first << " <---> " << pos->second << endl;
pos++;
}
}
The output is what I want;
I want to know what is the difference between use of iterator, what happended to the first iterator when I insert new key-value pair ? Thanks!
addtion:
compile is use gcc 4.1.2 , in feel more confused,like this :
Since you called begin() when the container was empty, you got an iterator that was equal to end() (§23.1/7: "If the container is empty, then begin() == end()").
Inserting items into the container didn't change that, so you still have pos == intIntMap.end().
You then execute zero iterations of your loop, since pos==end(), and you'r executing the loop only as long as pos != end().
In the second example, you set pos() after you've inserted the data, so you get the first items in the collection, and iterate to the last.
Edit: As far as printing out the contents of the map goes, I'd probably do it more like this:
std::ostream &operator<<(std::ostream &os, std::pair<int, int> const &d) {
return os << d.first << " <---> " << d.second;
}
// ...
std::copy(intIntMap.begin(), intIntMap.end(),
std::ostream_iterator<std::pair<int, int> >(std::cout, "\n"));
Going through this with gdb, I found that the first field of the iterator was changing with each addition of a key-value pair. It seems that an iterator to a map with no data in it (returned by begin()) contains some metadata about the map itself, specifically the size of the map (the first field of said iterator grew with each addition of a key-value pair). Calling begin() to retrieve the iterator after a single key-value pair is added results in the "expected" behavior.
Iterators are intended to be used on a container that has not been modified since the iterator instantiation. The code's output in the first example is undefined, according to the c++ standard (you could still get the result you want, you're just not guaranteed to get it, and there's not much of a reason to expect it).
Nothing happened to the iterator in the first case, but the container you intend it to refer to has undergone changes, and isn't necessarily at the same location in memory.
Container modification invalidates existing iterators.
The common practice is to get iterator just before using it, and then, throw it away. You could use for like this:
#include <iostream>
#include <map>
using namespace std;
int main ()
{
map<int, int> mymap;
mymap[0] = 100;
mymap[1] = 200;
mymap[2] = 300;
// show content:
for (map<int, int>::iterator it = mymap.begin(); it != mymap.end(); it++)
cout << (*it).first << " => " << (*it).second << endl;
return 0;
}
Short answer: there is no guarantee that the iterator is still valid after modifying the container contents.
Since the container here is a map, typically implemented as a red-black tree, the structure is modified and rebalanced during insertions.
In the first example, you are initialising the iterator pos to the start of the map. At this point, the iterator is valid for the current contents. But once you start adding elements, the iterator is no longer pointing to the new begin position of the reorganised container.
So the reason why the second example works is because you are setting the iterator to begin after all modifications to the container have been completed.
In general, it is a bad idea to modify a structure while iterating over it.
This question has some more details on validity of iterators:
Do STL iterators guarantee validity after collection was changed?

How do I know if std::map insert succeeded or failed?

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
Insert with hint method a 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 is then 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

Resources