Alias this with array can only be used once
Jonathan M Davis
jmdavisProg at gmx.com
Wed Feb 22 14:40:17 PST 2012
On Wednesday, February 22, 2012 23:28:47 Simen Kjærås wrote:
> On Wed, 22 Feb 2012 23:16:41 +0100, Blake Anderton <rbanderton at gmail.com>
>
> wrote:
> > Why doesn't this work? I'm assuming I'm not fully understanding how
> > "alias this" interacts with ranges (i.e. the range isn't being reset
> > after count is finished with it), but I'm not sure how to fix this
> > either:
> >
> > import std.algorithm;
> >
> > class ArrayContainer
> > {
> >
> > int[] values;
> > this(int[] v) { values = v; }
> > alias values this;
> >
> > }
> >
> > void main(string[] args)
> > {
> >
> > auto c = new ArrayContainer([1, 2, 3]);
> > assert(count(c) == 3); //succeeds
> > assert(c.length == 3); //FAILS - is actually zero
> >
> > }
>
> That's interesting. The thing that happens is the function popFront
> is callable on ArrayContainer, and popFront mutates its parameter.
> The solution is to use count(c[]), but I'm not so sure I agree with
> the way this works currently.
It's the consequence of having a container which is also a range - which is
what this code is doing. It's _not_ something that's a good idea.
Regardless, it's not like this code could have any other behavior than it
does. The template constraint on count verifies that the argument is an input
range, which it is, since you can call front, popFront, and empty on it thanks
to the alias this. So, the template gets instantiated with the type that you
pass it - ArrayContainer. And then ArrayContainer gets consumed by count as
any range would gets consumed by count. It's just that unlike most ranges,
it's a class, so it doesn't get implicitly sliced or saved when you pass it
in. So, instead of the slice being consumed, it itself is consumed.
This is all solved by just not declaring a container which is a range. It's
just asking for trouble. You don't want your container to be consumed when you
pass it to range-based functions. Rather, you should be slicing it so that the
_range_ gets consumed without screwing over your container.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list