This is a subtle issue. The point here is that after you modify the element pointed to by fr_it2
, you also implicitly modify fr_it1
because fr
is a lazy view on the original range. This means that the transformed
filter needs to be recomputed. This is a very non-intuitive property, because for eager STL ranges, modifications through iterators don't modify the iterators themselves, but for lazy ranges this is no longer true!
In fact, if you print the entire fr
and rf
ranges using "fresh" iterators, you will see that their contents are in fact the same.
fr_it2->first = false;
for (auto e : fr) std::cout << e.first << e.second << ";"; // prints 13;11
...
rf_it2->first = false;
for (auto e : rf) std::cout << e.first << e.second << ";"; // prints 13;11
Live Example 1. So in fact the middle element is indeed deleted!
I think you should not modify elements through iterators into the adapated range, but rather through iterators into your primary container, like this:
auto fr_it1 = container.begin();
...
auto rf_it1 = container_cpy.begin();
Live Example 2. If you do that, you get consistent results that show "0 2" for both approaches.