Re: input iterators and post increment
I don't understand what you mean. If your input iterator returns a
proxy result, there is no reason why this could cause the code to be
dangerous that could lead to random crashes. Would you please
elaborate?
But what value would the proxy object have? Set it to the value of
the previous iterator? Most importantly, where is it stored? In the
iterator itself? Great, every iterator now grows by sizeof(T) just
for this one case. As a static object? That wouldn't work for thread
safety. On the heap? Now we're hitting the memory allocator. This
is very slow, imagine if someone writes a post increment loop,
correctly throwing away the result. Every increment now does a
useless new and delete and nobody can even tell this is happening by
just looking at the code. Also now you have to track ownership,
handle moves/copies etc..
What happens if you increment the iterator holding
a proxy? The madness goes on and on. Better to just crash and
tell the programmer don't do that!
Basically my iterator class looks like this.
class Container::iterator {
public:
iterator()
: _first(nullptr), _last(nullptr), _parent(nullptr)
T& operator*() { assert(_first != nullptr); return *_first; }
T* operator->() { assert(_first != nullptr); return _first; }
iterator& operator++() {
assert(_first != nullptr);
if(_first != _last) {
++_first;
} else {
_parent->giveMeMore(&_first, &_last);
}
return *this;
}
iterator operator++(int) {
++(*this);
return iterator(); //<-asserts on dereference
}
private:
T* _first;
T* _last;
Container* _parent;
friend class Container;
iterator(T* f, T* l, Container *p)
: _first(f), _last(l), _parent(p) {}
};
The standard allows for past iterators to become invalidated. Instead
of waiting for this to happen by chance, I do it every time.
Dereferencing a past input iterator in this case is a programmer
error and thus should be caught and fixed as early as possible.
I don't understand for the hole here that needs to be fixed.
The hole specifically is the requirement for post increment for input
and output iterators. The operation makes no sense in this case. At the
very least, just relax the requirement for these 2 iterators and ensure
STL implementations will work correctly.
Maybe, but so is operator-> and the requirements have existed for
decades. Personally I would instead suggest to introduce a new
iterator category set that does better discriminate traversal and
access. When doing so, the requirement for post-fix increment could be
reconsidered or moved to higher-level iterator traversal categories.
operator-> may be syntactic sugar but its rather harmless and makes
code easier to write and understand. It's a "good" operator in my opinion.
The one beautiful thing about these operators is that raw pointers
become valid iterators. Even with raw pointers, you don't need to
ever use post-increment. For any generic algorithm which accepts
any iterator, it could easily be written to not use it.
We could introduce new weaker iterator categories but then what
would be the purpose of input and output iterators? They appear to
me to be the ones designed for this purpose.
It's inefficient for many non-pointer iterators, but it is not
dangerous. I don't think that an efficiency argument alone could
convince the committee to break code that exists since decades.
It is dangerous for input/ouput iterators.
It wouldn't break any code. The STL would simply stop calling
post-increment if it ever does and always use pre-increment. Anyone
who has correctly implemented an iterator has always implemented
pre-increment and copy construction.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]