digitalmars.D - Possible issue with isInputRange
- Maor Ben Dayan (39/39) Sep 23 2015 isInputRange will always return true for a range returning ref to
- Alex Parrill (9/49) Sep 24 2015 It's because you disabled the copy constructor of `Snowflake`.
- Lionello Lunesu (2/4) Sep 24 2015 What is `h`?
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
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
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