digitalmars.D.learn - isBidirectionalRange fails for unknown reasons
- Jack Stouffer (40/40) Dec 16 2015 I'm trying to add a ReferenceBidirectionalRange range type to
- Jack Stouffer (10/20) Dec 16 2015 Also, this works just fine
- anonymous (10/27) Dec 16 2015 The `.save` primitive of forward ranges must return the very same type
- Jack Stouffer (2/11) Dec 16 2015 Thanks! That did the trick.
- Jakob Ovrum (13/14) Dec 16 2015 You can also use return type covariance:
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
}
Dec 16 2015
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
}
Dec 16 2015
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);}
Dec 16 2015
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.
Dec 16 2015
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.
Dec 16 2015









Jack Stouffer <jack jackstouffer.com> 