Home > Mobile >  Why are insert iterators not copyable?
Why are insert iterators not copyable?

Time:01-05

The classes std::back_insert_iterator, std::front_insert_iterator and std::insert_iterator cannot be copied. Both the assignment operator and the constructor do not allow copies. Also the properties container (and iter in std::insert_iterator) are protected.

I wonder why. I'd like to copy these into a lambda function to use later to populate the containers.

Something like this doesn't seem possible:

template<class OutIter>
std::function<void()>
generateFunction(OutIter out_iter) {
    return
        [out_iter] // not possible and a reference becomes dangling
        () { 
            // write to outpit iterator.
        }
}

I'm just wondering why? It would be handy to be able to use the iterators here. Now I either have to build my own inserter or work directly on the containers. Or does anyone have another idea?

Edit: It seems to be copyable. But if i use it as a lambda capture, i got a const version of the inserter. This code does not compile:

#include <functional>
#include <vector>
#include <iterator>

template<class OutIter>
inline std::function<void(int)>
generateFunction(OutIter out_iter) {
    return
        [out_iter] (int value) {
            *out_iter = value;
              out_iter;
        };
}

int main() {
    std::vector<int> v;
    auto myFn = generateFunction(std::back_inserter(v));

    myFn(1);
    myFn(2);
}

Error is:

<source>:10:13: error: passing 'const std::back_insert_iterator<std::vector<int> >' as 'this' argument discards qualifiers [-fpermissive]
   10 |             *out_iter = value;

Solution: The Lambda has to be mutable:

template<class OutIter>
inline std::function<void(int)>
generateFunction(OutIter out_iter) {
    return
        [out_iter] (int value) mutable {
            *out_iter = value;
              out_iter;
        };
}

Many thanks for the helpful answers.

CodePudding user response:

The classes std::back_insert_iterator, std::front_insert_iterator and std::insert_iterator cannot be copied. Both the assignment operator and the constructor do not allow copies.

Your assumption is wrong. All of the iterators mentioned must satisfy the LegacyOutputIterator named requirement which implies that they also satisfy the LegacyIterator named requirement which requires the iterator to be copyable

Gcc, clang and MSVC all consider the iterators to be copyable, see godbolt.

CodePudding user response:

template <class Container>
  class insert_iterator :
    public iterator<output_iterator_tag,void,void,void,void>
{
protected:
  Container* container;
  typename Container::iterator iter;

public:
  typedef Container container_type;
  explicit insert_iterator (Container& x, typename Container::iterator i)
    : container(&x), iter(i) {}
  insert_iterator<Container>& operator= (typename Container::const_reference value)
    { iter=container->insert(iter,value);   iter; return *this; }
  insert_iterator<Container>& operator* ()
    { return *this; }
  insert_iterator<Container>& operator   ()
    { return *this; }
  insert_iterator<Container>& operator   (int)
    { return *this; }
};
  •  Tags:  
  • c
  • Related