On Friday, 17 November 2017 at 17:55:30 UTC, Jonathan M Davis wrote:

When you have

foreach(e; range)

it gets lowered to something like

for(auto r = range; !r.empty; r.popFront())
{
    auto e = r.front;
}

So, the range is copied when you use it in a foreach.

Indeed, and the language spec says so, but this is quite wrong as it violates the specification and design of ranges ... only forward ranges are copyable and only via their `save` function. I have an input range that can only be iterated once; if you try to do so again it's empty ... but the foreach implementation breaks that. You should be able to break out of the foreach statement, then run it again (or another foreach) and it should continue from where it left off, but copying breaks that. I need to know how many elements of my range were consumed; copying breaks that. I got around this by having a pointer to my state so only the pointer gets copied. I would also note that tutorials such as Ali Çehreli's "Programming in D – Tutorial and Reference" are unaware of this breakage:

"
Those three member functions must be named as empty, popFront, and front, respectively. The code that is generated by the compiler calls those functions:

    for ( ; !myObject.empty(); myObject.popFront()) {

        auto element = myObject.front();

        // ... expressions ...
    }
"


Reply via email to