www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Possible issue with isInputRange

reply Maor Ben Dayan <maor weka.io> writes:
isInputRange will always return true for a range returning ref to 
non-copyable type.
This is a problem when trying to work with chain etc. together 
with such ranges.
The problem is that the test in isInputRange should have been 
similar to A below instead of B (no need to try and assign the 
return value of front for the range to be an input range).
Below is a reduced code example.

Am I correct in assuming that this is a phobos bug ?

code example:

void main()
{
     import std.range;
     import std.traits;

     struct Snowflake {
         int x;
          disable this(this);
     }

     Snowflake[12] flakes;
     foreach(uint i; 0..flakes.length) {
         flakes[i].x = i;
     }
     alias R = Snowflake[];

     foreach(ref s; flakes[0..$]) { /* works just fine, I guess it 
is a valid input range */
         // do something
     }

     static assert(is(typeof((inout int = 0) { R r = R.init; })));
     static assert(is(typeof((inout int = 0) { R r = R.init; if 
(r.empty) {} })));
     static assert(is(typeof((inout int = 0) { R r = R.init; 
r.popFront(); })));
     static assert(is(typeof((inout int = 0) { R r = R.init; 
r.front; })));        /* A passes */
     static assert(is(typeof((inout int = 0) { R r = R.init; h = 
r.front; })));  /* B fails */
     static assert(isInputRange!(Snowflake[]));                    
               /* fails */
}
Sep 23 2015
next sibling parent Alex Parrill <initrd.gz gmail.com> writes:
On Wednesday, 23 September 2015 at 23:10:21 UTC, Maor Ben Dayan 
wrote:
 isInputRange will always return true for a range returning ref 
 to non-copyable type.
 This is a problem when trying to work with chain etc. together 
 with such ranges.
 The problem is that the test in isInputRange should have been 
 similar to A below instead of B (no need to try and assign the 
 return value of front for the range to be an input range).
 Below is a reduced code example.

 Am I correct in assuming that this is a phobos bug ?

 code example:

 void main()
 {
     import std.range;
     import std.traits;

     struct Snowflake {
         int x;
          disable this(this);
     }

     Snowflake[12] flakes;
     foreach(uint i; 0..flakes.length) {
         flakes[i].x = i;
     }
     alias R = Snowflake[];

     foreach(ref s; flakes[0..$]) { /* works just fine, I guess 
 it is a valid input range */
         // do something
     }

     static assert(is(typeof((inout int = 0) { R r = R.init; 
 })));
     static assert(is(typeof((inout int = 0) { R r = R.init; if 
 (r.empty) {} })));
     static assert(is(typeof((inout int = 0) { R r = R.init; 
 r.popFront(); })));
     static assert(is(typeof((inout int = 0) { R r = R.init; 
 r.front; })));        /* A passes */
     static assert(is(typeof((inout int = 0) { R r = R.init; h = 
 r.front; })));  /* B fails */
     static assert(isInputRange!(Snowflake[]));
               /* fails */
 }
It's because you disabled the copy constructor of `Snowflake`. Apparently `isInputRange` requires copyable elements (it does `auto h = r.front;` in its check). Also, just because it's compatible with foreach loops doesn't mean it's a range; it may be an object with `opApply` (such as `std.parallelism.parallel`
Sep 24 2015
prev sibling parent Lionello Lunesu <lionello lunesu.remove.com> writes:
On 24/09/15 07:10, Maor Ben Dayan wrote:
      static assert(is(typeof((inout int = 0) { R r = R.init; h =
 r.front; })));  /* B fails */
What is `h`?
Sep 24 2015