(Here is a link to this same code on Wandbox)C++17 introduces member functions extract and insert on node-based containers (such as set and map) so that single elements can be transferred from container A to container B without any move operations. It also adds member function merge to transfer all contents of container A into container B. But there's no range merge function provided by the STL as far as I can tell. So, inspired by this question, I decided to write an iterator adaptor similar to std::move_iterator but which can be used to extract and insert instead of moving. Here's my usage example:// snipped the definitions of classes K and V, but see the Wandbox if you careint main(){    using KV = std::pair<K,V>;    std::map<K,V> m1({        KV{ k1, v1 },        KV{ k2, v2 },        KV{ k3, v3 },    });    std::map<K,V> m2;    puts(Moving elements from m1 to m2...);#if 0    // the old boring way    for (auto it = m1.begin(); it != m1.end(); ) {        m2.insert( m1.extract(it++) );    }#else    // the shiny new way    auto begin = my::extract_iterator(m1, m1.begin());    auto end = my::extract_iterator(m1, m1.end());    auto out = my::insert_iterator(m2);    std::copy(begin, end, out);#endif    puts(...done!);    std::cout << Contents of m1: << std::endl;    for (auto&& [k, v]: m1) {        std::cout << k << ' ' << v << std::endl;    }    std::cout << Contents of m2: << std::endl;    for (auto&& [k, v]: m2) {        std::cout << k << ' ' << v << std::endl;    }}And here's the implementation:#include <algorithm>#include <cassert>#include <iostream>#include <map>namespace my{    template<typename Container>    class insert_iterator    {        Container *container;    public:        using iterator_category = std::output_iterator_tag;        using difference_type = void;        using value_type = void;        using pointer = void;        using reference = void;        insert_iterator(Container& c) : container(&c) {}        insert_iterator& operator*() { return *this; }        insert_iterator& operator++() { return *this; }        insert_iterator operator++(int) { return *this; }        template<class N>        insert_iterator& operator=(N&& nh)        {            container->insert(std::forward<N>(nh));            return *this;        }    };    template<typename Container, typename Iterator>    class extract_iterator    {        Container *container;        Iterator iterator;        bool secretly_advanced = false;    public:        using iterator_category = std::input_iterator_tag;        using difference_type = void;        using value_type = void;        using pointer = void;        using reference = void;        extract_iterator(Container& c, Iterator it) : container(&c), iterator(std::move(it)) {}        auto operator*() {            assert(!secretly_advanced);            secretly_advanced = true;            return container->extract(iterator++);        }        extract_iterator& operator++() {            if (!secretly_advanced) ++iterator;             secretly_advanced = false;            return *this;        }        extract_iterator operator++(int) {            auto copy = *this;            if (!secretly_advanced) ++iterator;             secretly_advanced = false;            return copy;        }        bool operator==(const extract_iterator& o) const {            return secretly_advanced == o.secretly_advanced && iterator == o.iterator;        }        bool operator!=(const extract_iterator& o) const { return !(*this == o); }    };} // namespace myNotice that I'm using the default rules for class template parameter type deduction.Notice that my input iterator (extract_iterator) sets its value_type to void. I'm not 100% sure that's kosher.The secretly_advanced stuff is unfortunately necessary because libstdc++ implements its std::copy as something likewhile (first != last) {    *d_first++ = *first;    ++first;}instead ofwhile (first != last) {    *d_first++ = *first++;}and evaluating *first in my case invalidates first.iterator, so I figured the best thing to do was to advance it inside operator* itself and just keep track of whether it'd already been secretly advanced or not.If I missed out on a chance to use some exciting new C++17ism, please tell me!
C++17 extract/insert iterators
c++;iterator;c++17