Drew
Drew

Reputation: 13398

std::map erase - pass iterator to wrong map

Take this snippet of C++:

#include <map>

int main() {
    std::map<int, int> m1;
    m1[1] = 2;

    std::map<int, int> m2;
    m2[3] = 4;
    m1.erase(m2.begin());

    return m2.size();
}

On godbolt: https://godbolt.org/z/mJBszn

This feels like it must be undefined behaviour. Is that correct? If so, which part of the standard says so?

Upvotes: 3

Views: 133

Answers (2)

user4581301
user4581301

Reputation: 33932

This feels like it must be undefined behaviour. Is that correct?

Yes.

If so, which part of the standard says so?

The standard slaps down this bit of silliness in [associative.reqmts] note 8. I am citing n4659 because it's what I have a link to and close to C++17. At this time C++20 is still too much of a moving target.

Diving down into [tab:container.assoc.req] we find three erase overloads that take iterators,

a.erase(q)
a.erase(r)
a.erase(q1, q2)

of which a.erase(r) is the one of interest to the asker.

The table only states what happens if the program behaves; however the preamble to this table states that

q denotes a valid dereferenceable constant iterator to a, r denotes a valid dereferenceable iterator to a, [q1, q2) denotes a valid range of constant iterators in a

In other words, if the iterator r is not from map a, a's end iterator, or has been invalidated or otherwise rendered undereferenceable, the contract is broken and the results have been left undefined.

I include q, q1 and q2 to show the rules are the same for a constant iterator and iterator ranges.

Upvotes: 5

BTables
BTables

Reputation: 4833

This is all in reference to C++17.

Edit 2** I take back what I originally said, I just thread through part of the c++ standard and from a comment. In §26.2.6 the standard states for a.erase(r) in the context of associative containers is "If no such element exists, returns a.end()." However, the standard also states "r denotes a valid dereferenceable iterator to a"

Since this is not the case for m2.begin(), this is not in line with the standard, thus undefined behavior.

Upvotes: 4

Related Questions