Boost logo

Boost Users :

Subject: Re: [Boost-users] Iterator Range, sub range of a desired size
From: Jeff Flinn (Jeffrey.Flinn_at_[hidden])
Date: 2012-10-31 08:17:25


On 10/30/2012 12:50 PM, David Kimmel wrote:
> I tried it out, yes you can get make_iterator_range with next to work.
> I like boost::next but for what I wanted it does not seem to work
> appropriately. Your example of
> "make_iterator_range(boost::next(b.begin, wSize), v.end())" will only
> skip the first "wSize" elements. What I want is a range that contains
> at most wSize elements (if possible) - taking them from after (and
> containing) a start index.
>
> Even my second attempt with this approach (commented out lines) does not
> work because next does not check to see if it is past end. Perhaps if
> there is a "min" method I could pass the "boost::next(v.begin() +
> (start-1), window)" and "v.end()".
>
> typedef vector<int> Vector;
> Vector v = { 1, 2, 3, 4, 5, 6, 7, 8 , 9, 10, 11 };
>
> cout << "--" << endl;
> for(auto i : v) { cout << i << " "; }
> cout << "\n--\n" << endl;
>
> const int start = 10;
> const int window = 4;
>
> auto r = boost::make_iterator_range(boost::next(v.begin(), start-1),
> v.end());
> auto r2 = boost::make_iterator_range(boost::prior(r.end(), window),
> r.end());
>
> //auto r = boost::make_iterator_range(v.begin() + (start-1),
> boost::next(v.begin() + (start-1), window) );
> //auto r2 = boost::make_iterator_range(boost::prior(r.end(), window),
> r.end());
>
> cout << "\n--\nr: ";
> for(auto i : r) { cout << i << " "; }
>
> cout << "\n--\nr2: ";
> for(auto i : r2) { cout << i << " "; }
>
> cout << "\n--\n" << endl;

Our application has lots of this type of index/range manipulation. So
much in fact it was worth factoring out a open/closed integer range
interval class(similar to boost ICL's):

class Interval
{
public:

static Interval makeInclusive(int first, int last);
static Interval makeExclusive(int begin, int end);

static Interval makeInclusiveNormalized(int val1, int val2);
static Interval makeExclusiveNormalized(int val1, int val2);

static Interval makeSized(int begin, int size);

template<class CONTAINER>
static Interval makeSized(const CONTAINER& c)
{ return makeSized(0, c.size()); }

int indexBegin() const { return m_begin; }
int indexEnd () const { return m_end; }

bool empty() const { return m_end == m_begin; }
std::size_t size() const { return m_end - m_begin; }

...
};

Interval intersection(const Interval& lhs, const Interval& rhs);
...

This separates the index math from the final range traversal while
providing higher level expression of the intent. Then we can construct a
boost::adaptors::sliced using:

inline boost::adaptors::sliced slicedFrom(const Interval& i)
  { return boost::adaptors::sliced(i.indexBegin(), i.indexEnd()); }

and use it:

int main()
{
std::vector<float> v(42);

Interval vi = Interval::makeSized(v);
Interval i = Interval::makeExclusive(37, 93);

boost::fill(v | slicedFrom(intersection(vi, i)), 123.456f);

return 0;
}

Jeff


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net