Boost logo

Boost :

Subject: Re: [boost] AlRangeExandrescu?
From: Neil Groves (neil_at_[hidden])
Date: 2009-07-28 13:19:20

On Tue, Jul 28, 2009 at 5:54 PM, Andrei Alexandrescu <
andrei_at_[hidden]> wrote:

> Thorsten Ottosen wrote:
>> Andrei Alexandrescu skrev:
>>> Thorsten Ottosen wrote:
>>>> Stewart, Robert skrev:
>>>>> Steven Watanabe wrote:
>>>> How about another try: traversing a range with changing criteria?
>>>>>>> A particular range class can take a predicate or some other
>>>>>>> traversal influencing argument that can change with each
>>>>>>> advance. How would you express that with iterator pairs?
>>>>>> Easily. First of all, consider what's possible if the two iterators
>>>>>> are allowed to be different types. Then all the actual state can
>>>>>> be put in the first iterator and comparison to the second iterator
>>>>>> can just check whether the range is empty. Once you have that,
>>>>>> you can use boost::variant to store both iterators as the same type.
>>>>>> This will not be efficient, but it will work.
>>>>> That may well work, but the range version would certainly be more
>>>>> straightforward and,
>>>> >as you noted, efficient. Of course, once you permit the iterators to
>>>> have different types,
>>>> >you also increase the opportunity for mixing them incorrectly, which
>>>> won't happen with an Alexandrescu range.
>>>> I think we all agree that Alexandrescu ranges are conceptually simpler
>>>> to implement and specify; however, from a user perspective the two
>>>> approaches should be be similar.
>>> Well ranges seem to make functional composition easier because one object
>>> represents what you need, not two.
>> By the other approach I meant what Boost.Range and RangeEx is offering.
>> Not the iterator approach.
> Oh, I see. Sorry. I think with Boost::Range you can indeed do what you can
> do with a primitive range. The downsides that I see are (a) you need to mind
> the occasional wart, e.g. defining dummy iterators; (b) given that users can
> always tease out the iterators, you need to define iterators anyway, with
> the occasional loss in safety or efficiency; (c) you may occasionally waste
> some space by holding an extra iterator when not needed. The upside is that
> you have access to a few idioms that are gauche with primitive ranges.
> One possible way to combine the advantages of the two is to define a
> flexible interface for Boost::Range(Ex). Say for example that Boost::RangeEx
> defines empty, front, pop_front, and optionally the obvious extensions for
> bidir and random-access (back, pop_back, and operator[]). So far so good.
> People who only need these operations will find them convenient.

This is what I have prototyped in the Boost.RangeEx code that should be in
the trunk soon.

> Now here comes an interesting possibility. Boost::RangeEx also defines a
> typename Boost::RangeEx::iterator, and begin() and end() that return
> iterators. But it makes them optional! Meaning, as much as there are forward
> vs. bidirectional ranges, there are ranges that cloak iterators versus
> ranges that don't. Then algorithms that do use begin() and end() can only
> work with "iterator ranges" and those that don't can work with iterator
> ranges but also with "primitive ranges". Then, whoever wants to define a
> range either goes through the iterator route or just defines the range
> primitives.

I'm unsure what the Boost::RangeEx::iterator would be, and why we need such
a thing. Since we have non-member functions for boost::begin(end),
boost::end(rng) we can have ranges that model the newer concepts not
implement the begin(), end() ,member functions. It seems that the
pop_front(), pop_back(), operator[] map onto advance_begin(), advance_end()
on our existing implementation of iterator_range. Currently it appears that
the non-member functions already in Boost.RangeEx make the support for both
the Boost.Range-esque ranges and the Alexandrescu-esque ranges possible, if
not necessarily simple.

Why can't we use an iterator adaptor around the range primitive to keep the
capability for algorithms based on begin() and end() to work with the new
Range primitives? I think this would maintain backward compatibility, while
allowing us to define new algorithms taking advantage of the newer concepts.

> Andrei

I greatly appreciate your significant time and contributions in helping the
C++ and Boost community learn from the work you have done in D.

Warmest Regards,
Neil Groves

Boost list run by bdawes at, gregod at, cpdaniel at, john at