"Mike Austin" <mi**@mike-austin.com> wrote in message
news:s6******************@bgtnsc05-news.ops.worldnet.att.net...
"Ivan Vecerina" <IN*************************@vecerina.com> wrote in
message
news:cl**********@newshispeed.ch...
..... Finally, note that some implementations of the standard library
support a debug mode where the ranges of all iterators (and
other consistency checks) are made automatically.
(STLport is one such implementation, I do not know about gcc's).
This doesn't help write portable code, but can be helpful
during debugging.
I would like to use exceptions, rather than put code checks around
everything. It's just cleaner and more structured.
I don't know exactly how to implement 'safe_iterator', but the following
is
a start. Would anyone like to give me a hint?
template <typename T>
class safe_iterator : public T::iterator {
Derivation is unsafe here (especially once you need
to add a data member). Unfortunately you should prefer
containment (store the base iterator as a data member).
Value operator ++() {
if( *this == container->end() ) // how to access "container"?
throw out_of_range( "operator vector ++(): out of range" );
else
T::iterator::operator ++();
}
};
You need to store a pointer to the container within the iterator.
Then you can use it to test for valid bounds, but eventually also
for validating iterator pairs during comparisons.
For example:
template<typename T>
bool operator ==( safe_iterator<T> const& a
, safe_iterator<T> const& b )
{
if( a.pContainer != b.pContainer ) throw( .... );
return a.base == b.base;
};
[ What you cannot reliably check for this way is whether the
iterator is being used after having been invalidated
by a call modifying the contents of the container ]
It is not a trivial task to implement a complete iterator
interface, although some libraries can help with this
(
http://www.boost.org/libs/utility/op....htm#iterator).
But in the end, implementing fully checked iterators
takes some real effort, and implies that many redundant
error checks will be included in the compiled code.
The philosophy of the STL is that operations are performed
on a valid range specified by two iterators. This way you
check upfront that the range is valid/has enough elements,
and then you perform all operations without further overhead.
I do not know specifically what you are implementing, but
if fully implementing a safe iterator seems excessively
complex, maybe you can try to adapt your approach to the
problem?
Alternatively, consider writing a few non-member functions
that encapsulate the essential operations for which you need
range checking.
E.g.:
template<class Cont, class Iter>
Iter checkedOffset(Cont const& c, Iter const& p, int offset)
{
if( offset>0 && (c.end() - p)<=offset ) throw(....);
if( offset<0 && (c.begin()-p)> offset ) throw(....);
return p+offset;
}
Regards,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <>
http://www.brainbench.com