lundi 2 mars 2015

Can I assign a value to the element pointed at by the iterator returned by map::emplace?

map::emplace returns a pair<iterator,bool>.


The C++ standard at 23.2.3 Sequence containers paragraph 11 (I think that's the numbering scheme, anyway, near the top of page 755 of the Nov 2014 draft) says about emplace:



The iterator returned from a.emplace(p. args) points to the new element constructed from args into a.



Then in Table 102 on associative containers on page 760 it says about a_uniq.emplace(args) that



the iterator component of the pair points to the element with key equivalent to the key of t.



So I took "points to the element" to mean that it, you know, points to the element in the map, and that you can overwrite the value in the map by assignment. (And the key as well, which would probably break the map.) Because if they didn't want you to do that the first element of the return value pair would be a const_iterator, not an iterator, right?


But not so. The following code (also see it at ideone) shows that whatever it is you're assigning to isn't the value in the map:



#include <map>
#include <stdio.h>


struct st
{
int a;
int b;

st(int aa = 0, int bb = 0) : a(aa), b(bb) { }
};

void verify(std::string msg, std::map<int,st>& m, int key, int a, int b)
{
const st st = m[key];
if (st.a == a && st.b == b)
{
printf("ok %s: a == %d, b == %d\n", msg.c_str(), st.a, st.b);
}
else
{
printf("*** %s: a == %d (not %d), b == %d (not %d)\n", msg.c_str(), st.a, a, st.b, b);
}
}

int main(void)
{
std::map<int,st> a_map;

st st11(1,1);
st st35(3,5);

a_map[9] = st11;
verify("m9 {1,1}", a_map, 9, 1, 1);

auto r = a_map.emplace(9, st35);

printf("emplace {3,5} at 9: %s\n", r.second ? "inserted" : "existing");
verify("m9 {1,1}", a_map, 9, 1, 1);

auto pr = *r.first;
pr.second = st35;

verify("m9 {3,5}", a_map, 9, 3, 5);

return 0;
}


Which outputs the following for VC++ 2012 and gcc-4.9.2:



ok m9 {1,1}: a == 1, b == 1
emplace {3,5} at 9: existing
ok m9 {1,1}: a == 1, b == 1
*** m9 {3,5}: a == 1 (not 3), b == 1 (not 5)


So obviously the iterator isn't pointing to the element in the actual map structure.


What did I misinterpret here, in the standard (or the example code, or whatever)?


Aucun commentaire:

Enregistrer un commentaire