opIndex, opSlice, length for joiner?
Jonathan M Davis via Digitalmars-d
digitalmars-d at puremagic.com
Fri Jan 22 03:23:05 PST 2016
On Friday, 22 January 2016 at 10:18:20 UTC, Maverick Chardet
wrote:
> On Friday, 22 January 2016 at 01:02:10 UTC, Andrei Alexandrescu
> wrote:
>> On 01/21/2016 05:22 PM, Maverick Chardet wrote:
>>> Just a question: is it possible for a range to be considered
>>> infinite
>>> and at the same time have a length? I suppose that if it is
>>> possible,
>>> such a range would be ill-formed...
>>
>> Indeed that range would be ill-formed. -- Andrei
>
> Okay so I'll just use an assert!
>
>
> Something is bothering me though, I'm wondering why walkLength
> does not save the range when possible (when it is an input
> range)? For now it's just making a copy, couldn't it be
> problematic in some cases? The current code is:
>
>
> auto walkLength(Range)(Range range)
> if (isInputRange!Range && !isInfinite!Range)
> {
> static if (hasLength!Range)
> return range.length;
> else
> {
> size_t result;
> for ( ; !range.empty ; range.popFront() )
> ++result;
> return result;
> }
> }
>
>
> Why not something like this:
>
>
> auto walkLength(Range)(const ref Range range)
> if (isInputRange!Range && !isInfinite!Range)
> {
> static if (hasLength!Range)
> return range.length;
> else
> {
> size_t result;
> static if (isForwardRange!range)
> {
> Range rangeCopy = range.save;
> }
> else
> {
> Range rangeCopy = range;
> }
> for ( ; !rangeCopy.empty ; rangeCopy.popFront() )
> ++result;
> return result;
> }
> }
Arguably, walkLength shouldn't even accept a range that isn't a
forward range, since if it's not, then walkLength is just going
to eat the range. As for calling save, there's no point. It's too
late as soon as you've passed the range into the function, since
that copied the range, which is undefined behavior due to the
fact that the exact semantics of copying a range vary wildly
depending on how a range is implemented. In generic code, if you
want to use a range after passing it to a function, you have to
call save and pass that to the function; otherwise, you get
undefined behavior when you do anything with the range after
passing it to the function.
Also, I would point out that passing by const ref isn't going to
work. The range would be const, so you couldn't iterate over it
(and save returns the exact same type as the range, so it
wouldn't remove const even if it could - at it probably can't
anyway). And if the function takes the range by ref, then it will
consume it, which you really don't want. Calling save would get
around that problem, but then you'd still have the problem that
the function wouldn't accept rvalues, which would be highly
annoying.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list