Alias this with array can only be used once
Jonathan M Davis
jmdavisProg at gmx.com
Wed Feb 22 14:35:12 PST 2012
On Wednesday, February 22, 2012 23:16:41 Blake Anderton 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
> }
I believe that the problem stems from the fact that count is being
instantiated with ArrayContainer rather than int[]. That means that when it
gets processed, it ends up operating on the array directly rather than on a
slice. If ArrayContainer were a struct rather than a class, then this would
work.
But by doing what you're doing, you've managed to create a type that
effectively conflates a range and a container. So, when you pass it to range-
based functions, it _will_ be consumed.
You really shouldn't give direct access to the array like that. It's only
going to cause you trouble. Containers should _not_ be ranges, and using alias
this makes your ArrayContainer a range.
Instead, you should provide an opSlice to get the array. Then you'd do
assert(count(c[]) == 3);
assert(c[].length == 3);
The explicit [] would be required to call opSlice, since ArrayContainer would
then not be passable to count (which it really shouldn't be anyway).
However, if you're really married to the idea of using alias this, then the
above code will work with your current implementation, since it forces the
array to be sliced, and count therefore gets instantiated with int[] rather
than ArrayContainer.
But again, I _really_ advise against having a container which is a range. It's
a _bad_ idea which is only going to cause you trouble.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list