output ranges: by ref or by value?

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sat Jan 2 10:06:25 PST 2010


Steven Schveighoffer wrote:
> On Fri, 01 Jan 2010 18:45:35 -0500, Andrei Alexandrescu 
> <SeeWebsiteForEmail at erdani.org> wrote:
> 
>> Rainer Deyke wrote:
>>> Andrei Alexandrescu wrote:
>>>> If the implementor of consume() forgets to call save(), the 
>>>> situation is
>>>> unpleasant albeit not catastrophic: for most struct ranges things will
>>>> continue to work, but for class ranges the function will fail to 
>>>> perform
>>>> to spec. I don't know how to improve on that.
>>>  Require that all ranges are structs.  If you want to implement a range
>>> as a class, use a wrapper struct that creates a new object in its
>>> postblit function.  The wrapper struct can be made generic and placed in
>>> the standard library.
>>>  Same performance as the current approach, slightly more effort on the
>>> part of the range implementor, much easier and less error-prone on the
>>> side of the range user.
>>
>> Oh, besides it doesn't work for struct ranges that iterate one-pass 
>> streams.
> 
> What does save do in those cases?
> 
> -Steve

It provides a syntactic differentiation between input ranges and forward 
ranges.

STL's input iterators are syntactically indistinguishable from forward 
iterators. Because of that, all STL algorithms that expect forward 
ranges will also compile and run with input ranges, although never with 
the expected result. This has been a lingering problem with C++98, and a 
key motivator for concepts. Since syntactic differences cannot be used 
to distinguish between input and forward iterators, the reasoning went, 
we need something else as a discriminator - and that would be a concept: 
someone who defines an input iterator declares it obeys the input 
iterator concept, whereas someone defining a forward iterator declares 
it obeys the forward iterator concept.

During the meltdown of concepts, a number of people including Bjarne 
Stroustrup and myself have suggested that a simple workable solution 
would be to define an extra function a la "save" that is used in 
algorithms and only supported by forward iterators, but not by input 
iterators. Then, algorithms use save() and will correctly refuse to 
compile calls with input iterators. The remaining risk is that someone 
writes an algorithm and forgets to use save().


Andrei



More information about the Digitalmars-d mailing list