Alias this with array can only be used once

Jonathan M Davis jmdavisProg at gmx.com
Wed Feb 22 15:42:30 PST 2012


On Thursday, February 23, 2012 00:16:00 Blake Anderton wrote:
> Thanks all for the quick replies.
> 
> You're right- I am mixing the container with the range to ill
> effect. I'm just doing this for practice so I'm not tied to any
> one solution, but I was trying to make the container work as much
> like a built-in type as possible. With an array the above tests
> work (I assume because each operation is implicitly a new slice?).
> 
> I found I can fix the above example by aliasing a function that
> returns a slice of the member array instead of aliasing the field
> itself, but that may still be too close a relationship of the
> container/range. My instinct (which could be completely wrong) is
> that it's fine since the container is taking responsibility for
> creating valid ranges, it is just doing so implicitly.
> 
> User code having to explicitly take ranges (either through
> opSlice or a property/method) isn't a terrible thing, but it
> would be convenient to not have to take that extra step.

That's just the way that it works with containers.

Dynamic arrays are weird in that they're not really containers, but people 
tend to think of them as containers. But they don't own their own memory, and 
they're ranges. Static arrays _are_ containers and act like containers should 
in that they require you to slice them to pass to range-based functions, 
because that's what you have to do to get a range over them.

In any case, a container is not a range and shouldn't be treated as one. Your 
solution with an aliased function sort of solves the problem and sort of not. 
Your container is still considered a range, but when you go to use it as a 
range, you end up getting a slice of the internal array, which _is_ a range. 
I'd advise just making a clear distinction between the container and the range 
and not using alias this. alias this is great when you want to treat one type 
like another, but that's _not_ what we want with containers and ranges. 
Conflating the two will cause problems, much as might be able to get away with 
it in some cases.

The standard way to do it (as std.container's types do) is to have the 
container have _no_ range functions at all but to implement opSlice which 
returns a range over that container.

When it comes to containers, you really shouldn't think of ranges as being 
similar to iterators. And you wouldn't make a container into an iterator would 
you? Conflating the two would not be pretty. Unfortunately, with ranges, the 
distinctious isn't as obvious, since they refer to a range of elements rather 
than a single element, but the problem is still essentially the same.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list