Update:
Thanks to everyone who submitted an answer.
In short, the answer is that the "iterators" that begin()
and end()
return must be copyable.
Artyer proposed a nice workaround: Make an iterator class that contains a reference (or, alternatively, a pointer) to the non-copyable object. Below is example code:
struct Element {};
struct Container {
Element element;
struct Iterator {
Container * c;
Iterator ( Container * c ) : c(c) {}
bool operator != ( const Iterator & end ) const { return c != end.c; }
void operator ++ () { c = nullptr; }
const Element & operator * () const { return c->element; }
};
Iterator begin () { return Iterator ( this ); }
Iterator end () { return Iterator ( nullptr ); }
};
#include <stdio.h>
int main () {
Container c;
printf ( "main %p\n", & c .element );
for ( const Element & e : c ) { printf ( "loop %p\n", & e ); }
return 0;
}
Original Question:
The below C++ code will not compile (at least not with g++
version 9.3.0 on Ubuntu 20.04).
The error message is:
use of deleted function 'Iterator::Iterator(const Iterator&)'
Based on the error, am I correct in concluding that the "iterators" returned by begin()
and end()
must be copyable? Or is there some way to use a non-copyable iterator that is returned by reference?
struct Iterator {
Iterator () {}
// I want to prevent the copying of Iterators, so...
Iterator ( const Iterator & other ) = delete;
bool operator != ( const Iterator & other ) { return false; }
Iterator & operator ++ () { return * this; }
Iterator & operator * () { return * this; }
};
struct Container {
Iterator iterator;
Iterator & begin() { return iterator; }
Iterator & end() { return iterator; }
};
int main () {
Container container;
for ( const Iterator & iterator : container ) {}
// The above for loop causes the following compile time error:
// error: use of deleted function 'Iterator::Iterator(const Iterator&)'
return 0;
}