On Sunday, February 16, 2020 10:53:36 AM MST Paul Backus via Digitalmars-d- learn wrote: > On Sunday, 16 February 2020 at 17:10:24 UTC, Jonathan M Davis > > wrote: > > On Sunday, February 16, 2020 7:29:11 AM MST uranuz via > > > >> This is working fine with disabled postblit... > >> import std; > >> > >> struct SS > >> { > >> > >> @disable this(this); // Disabled copy > >> > >> bool _empty = false; > >> > >> bool empty() @property { > >> > >> return _empty; > >> > >> } > >> > >> void popFront() { > >> > >> _empty = true; > >> > >> } > >> > >> int front() @property { return 10; } > >> > >> } > >> > >> > >> void main() > >> { > >> > >> foreach( it; SS() ) { writeln(it); } > >> > >> } > >> > >> Am I missing something? > > > > That code compiles, because you're passing a temporary to > > foreach. So, the compiler does a move instead of a copy. It's > > the difference between > > > > auto ss = SS(); > > > > and > > > > SS ss; > > auto ss2 = ss; > > > > If your main were > > > > void main() > > { > > > > SS ss; > > foreach( it; ss ) { writeln(it); } > > > > } > > > > then it would not compile. > > On the other hand, this does work: > > void main() > { > SS ss; > foreach( it; move(ss) ) { writeln(it); } > } > > So perhaps the correct approach is to use `move` when copying > input ranges.
Given that the way that almost all range-based functions work is to copy the range that they're given (often then wrapping it in another range that's returned), I don't see how it would make sense to use move outside of very specific circumstances. If you pass a range to a function, and it's a basic input range, then you just use the range via the return value (be it the same range returned directly or returned within a wraper range), and if it's a forward range, you call save before passing it to the function if you want to be able to use the range directly again. Either way, generic code should never be using a range after it's been copied, and copying is a key part of how idiomatic, range-based code works in D. And really, using move just to be able to use an uncopyable range with foreach doesn't make a lot of sense, since if that's what you want to do, you can always just use a normal for loop. Regardless, there isn't much point in declaring a range type that can't be copied, since it's pretty much only going to work with code that you write. - Jonathan M Davis