Difference between range `save` and copy constructor
Jonathan M Davis
newsgroup.d at jmdavisprog.com
Sun Feb 16 17:10:24 UTC 2020
On Sunday, February 16, 2020 7:29:11 AM MST uranuz via Digitalmars-d-learn
wrote:
> On Sunday, 16 February 2020 at 12:38:51 UTC, Jonathan M Davis
>
> wrote:
> > On Sunday, February 16, 2020 3:41:31 AM MST uranuz via
> >
> > Digitalmars-d-learn wrote:
> >> I have reread presentation:
> >> http://dconf.org/2015/talks/davis.pdf
> >> We declare that `pure` input range cannot be `unpoped` and we
> >> can't return to the previous position of it later at the time.
> >> So
> >> logically there is no sence of copying input range at all. So
> >> every Phobos algorithm that declares that it's is working with
> >> InputRange must be tested for working with range with disabled
> >
> > A range that can't be copied is basically useless. Not only do
> > almost all range-based algorithms take their argumenst by value
> > (and thus copy them), but foreach copies any range that it's
> > given, meaning that if a range isn't copyable, you can't even
> > use it with foreach. And since many range-based algorithms
> > function by wrapping one range with another, the ability to
> > copy ranges is fundamental to most range-based code.
>
> 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.
foreach(e; range) {...}
basically gets lowered to
for(auto __r = range; !__r.empty; __r.popFront())
{
auto e = __r.front;
...
}
So,
foreach( it; SS() ) { writeln(it); }
would become
for(auto __r = SS(); !__r.empty; __r.popFront())
{
auto it = __r.front;
writeln(it);
}
whereas
SS ss;
foreach( it; ss ) { writeln(it); }
would become
SS ss;
for(auto __r = ss; !__r.empty; __r.popFront())
{
auto it = __r.front;
writeln(it);
}
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list