It's undefined behaviour, and won't work reliably. After adding a line to print keys and values inside your erasing lambda function, I see:
1=5000 2=1 3=2 4=5000 2=1 // AGAIN!!! 3=2 // AGAIN!!! 5=5000 6=3
With my Standard library's map implementation, after erasing the element with key 4, iteration returns to the node with key 2! It then revisits the node with key 3. Because your lambda happily retested such nodes (v.second > 1000) and returned without any side effects, the broken iteration wasn't affecting the output.
You might reasonably ask: "but isn't it astronomically unlikely that it'd have managed to continue iteration (even if to the wrong next node) without crashing?"
Actually, it's quite likely.
Erasing a node causes delete to be called for the memory that node occupied, but in general the library code performing the delete will just:
invoke the destructor (which has no particular reason to waste time overwriting the left-child-, right-child- and parent-pointers), then
modify its records of which memory regions are allocated vs. available.
It's unlikely to "waste" time arbitrarily modifying the heap memory being deallocated (though some implementations will in memory-usage debugging modes).
So, the erased node probably sits there intact until some other heap allocation's performed.
And, when you erase an element in a map, the Standard requires that none of the container's other elements be moved in memory - iterators, pointers and references to other elements must remain valid. It can only modify nodes' left/right/parent pointers that maintain the binary tree.
Consequently, if you continue to use the iterator to the erased element, it is likely to see pointers to the left/right/parent nodes the erased element linked to before erasure, and operator++() will "iterate" to them using the same logic it would have employed if the erased element were still in the map.
If we consider an example map's internal binary tree, where N3 is a node with key 3:
N5 / \ N3 N7 / \ / N1 N4 N6
The way iteration is done will likely be:
initially, start at the N1; the map must directly track where this is to ensure begin() is O(1)
if on a node with no children, repeat { Nfrom = where you are, move to parent, if nullptr or right != Nfrom break} (e.g. N1->N3, N4->N3->N5, N6->N7->N5->nullptr)
if on a node with right-hand child, take it then any number of left-hand links (e.g. N3->N4, N5->N7->N6)
So, if say N4 is removed (so N3->right = nullptr;) and no rebalancing occurs, then iteration records NFrom=N4 then moves to the parent N3, then N3->right != Nfrom, so it will think it should stop on the already-iterated-over N3 instead of moving on up to N5.
On the other hand, if the tree has been rebalanced after the erase, all bets are off and the invalidated iterator could repeat or skip elements or even iterate "as hoped".
This is not intended to let you reason about behaviour after an erase - it's undefined and shouldn't be relied on. Rather, I'm just showing that a sane implementation can account for your unexpected observations.
std::remove_if.