1

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.

  • 2
    https://stackoverflow.com/questions/53445857/why-is-a-lambdas-call-operator-implicitly-const – Mat Jan 05 '23 at 11:49
  • 1
    *But if i use it as a lambda capture, i got a const version of the inserter.* You need to make you lambda `mutable`. – sklott Jan 05 '23 at 11:53

2 Answers2

3

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.

fabian
  • 80,457
  • 12
  • 86
  • 114
  • There might be issues arising from copying the `std::function` object so returned, when capturing single-pass output iterators – Caleth Jan 05 '23 at 11:23
  • Ok, i have edited my question. How to copy one of the insert iterators into a lambda? It seems to be converted into a useless `const` iterator. – Marcus Hampel Jan 05 '23 at 11:47
-4
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; }
};
Rahul Dev
  • 1
  • 1
  • 1
    Please read about [how to write good answers](https://stackoverflow.com/help/how-to-answer). And probably about [`std::iterator`](https://en.cppreference.com/w/cpp/iterator/iterator) as well. And don't try to get others into the same [cargo cult](https://en.wikipedia.org/wiki/Cargo_cult_programming) as you seem to have fallen into. – Some programmer dude Jan 05 '23 at 11:10