User defined type and foreach

Jim Balter Jim at Balter.name
Fri Jan 19 10:49:29 UTC 2024


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 ...
     }
"




More information about the Digitalmars-d-learn mailing list