Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
December 16, 2015 isBidirectionalRange fails for unknown reasons | ||||
---|---|---|---|---|
| ||||
I'm trying to add a ReferenceBidirectionalRange range type to std.internal.test.dummyrange so I can test some range code I'm writing, but I've hit a wall and I'm not sure why. For some reason, the isBidirectionalRange check fails even though back and popBack are present. Any help here would be appreciated. the code: ============================ import std.range; class ReferenceInputRange(T) { import std.array : array; this(Range)(Range r) if (isInputRange!Range) { _payload = array(r); } final @property ref T front(){ return _payload.front; } final void popFront(){ _payload.popFront(); } final @property bool empty(){ return _payload.empty; } protected T[] _payload; } class ReferenceForwardRange(T) : ReferenceInputRange!T { this(Range)(Range r) if (isInputRange!Range) { super(r); } final @property ReferenceForwardRange save() {return new ReferenceForwardRange!T( _payload); } } class ReferenceBidirectionalRange(T) : ReferenceForwardRange!T { this(Range)(Range r) if (isInputRange!Range) { super(r); } final @property ref T back(){ return _payload.back; } final void popBack(){ _payload.popBack(); } } unittest { static assert(isInputRange!(ReferenceInputRange!int)); // works static assert(isForwardRange!(ReferenceForwardRange!int)); // works static assert(isBidirectionalRange!(ReferenceBidirectionalRange!int)); //fails } |
December 16, 2015 Re: isBidirectionalRange fails for unknown reasons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack Stouffer | On Wednesday, 16 December 2015 at 20:43:02 UTC, Jack Stouffer wrote: > unittest > { > static assert(isInputRange!(ReferenceInputRange!int)); // works > static assert(isForwardRange!(ReferenceForwardRange!int)); // works > static assert(isBidirectionalRange!(ReferenceBidirectionalRange!int)); //fails > } Also, this works just fine ================= unittest { auto a = new ReferenceBidirectionalRange!int([1,2]); a.popBack(); a.back.writeln; // prints 1 } |
December 16, 2015 Re: isBidirectionalRange fails for unknown reasons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack Stouffer | On 16.12.2015 21:43, Jack Stouffer wrote: > I'm trying to add a ReferenceBidirectionalRange range type to > std.internal.test.dummyrange so I can test some range code I'm writing, > but I've hit a wall and I'm not sure why. For some reason, the > isBidirectionalRange check fails even though back and popBack are > present. Any help here would be appreciated. > [...] > > class ReferenceForwardRange(T) : ReferenceInputRange!T > { > this(Range)(Range r) if (isInputRange!Range) { super(r); } > final @property ReferenceForwardRange save() > {return new ReferenceForwardRange!T( _payload); } > } > > class ReferenceBidirectionalRange(T) : ReferenceForwardRange!T > { > this(Range)(Range r) if (isInputRange!Range) { super(r); } > final @property ref T back(){ return _payload.back; } > final void popBack(){ _payload.popBack(); } > } The `.save` primitive of forward ranges must return the very same type that the range has. But your ReferenceBidirectionalRange!T.save returns a ReferenceForwardRange!T, because it's inherited. That makes isForwardRange!(ReferenceBidirectionalRange!T) fail, and everything that depends on it. You can override `save` in ReferenceBidirectionalRange or try something clever like using a template this parameter: @property auto save(this This)() {return new This( _payload);} |
December 16, 2015 Re: isBidirectionalRange fails for unknown reasons | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Wednesday, 16 December 2015 at 21:40:44 UTC, anonymous wrote:
> The `.save` primitive of forward ranges must return the very same type that the range has. But your ReferenceBidirectionalRange!T.save returns a ReferenceForwardRange!T, because it's inherited. That makes isForwardRange!(ReferenceBidirectionalRange!T) fail, and everything that depends on it.
>
> You can override `save` in ReferenceBidirectionalRange or try something clever like using a template this parameter:
>
> @property auto save(this This)() {return new This( _payload);}
Thanks! That did the trick.
|
December 17, 2015 Re: isBidirectionalRange fails for unknown reasons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jack Stouffer | On Wednesday, 16 December 2015 at 20:43:02 UTC, Jack Stouffer wrote:
> ...
You can also use return type covariance:
class ReferenceBidirectionalRange(T) : ReferenceForwardRange!T
{
this(Range)(Range r) if (isInputRange!Range) { super(r); }
final override @property typeof(this) save() { return new typeof(this)(_payload); }
final @property ref T back(){ return _payload.back; }
final void popBack(){ _payload.popBack(); }
}
ReferenceBidirectionalRange!T is a subtype of ReferenceForwardRange!T, so the override is legal.
|
Copyright © 1999-2021 by the D Language Foundation