Boost logo

Boost :

From: Sam Saariste (ss_march2001_at_[hidden])
Date: 2005-06-04 14:19:00


"Peter Dimov" <pdimov_at_[hidden]> wrote in message
news:<001001c5686f$8c19d950$6501a8c0_at_pdimov>...
> Neal Becker wrote:
>
> > Here's my version:
>
> [...]
>
> One interesting problem with strided iterators is coming up with end
values.
> Suppose you have
>
> int x[ 4 ];
>
> and you want to iterate over x[1] and x[3] with stride 2. Your begin
> iterator will be x+1, and your end iterator will be x+5 - an invalid
> address.
>
I don't think end values are a difficult problem as long as the size of the
range is guaranteed to be a multiple of the stride and I have always found
this to be a reasonable restriction. In addition to the stride, the iterator
interface does need an offset parameter.

In your example the size of the range is indeed a muliple of the stride, so
there is a simple solution: store the underlying iterator without offset and
add the offset when dereferencing the iterator. In that case your underlying
iterator would take the values, &x[0], &x[2], and &x[4] - a valid
one-passed-the-end iterator that can be compared to the end slice iterator.

So relating to your example I would write something like:
std::for_each(
    slice_iterator<int*,2,1>(boost::begin(x)),
    slice_iterator<int*,2,1>(boost::end(x)),
    do_stuff);

and that works fine (as long as size of x is a multiple of the stride.

An interesting consequence of this approach is that for a slice iterator
with a run-time specified stride and offset, the end slice iterator does
_not_ depend on its stride or offset. I have made this an explicit feature
of a slice iterator I once wrote and found this to be very convenient as I
always ended up iterating n times over a range for a stride of n (each time
with a different offset).

Sam Saariste


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk