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
andstd::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; }
};