Alias this with array can only be used once

Jonathan M Davis jmdavisProg at gmx.com
Wed Feb 22 16:46:56 PST 2012


On Wednesday, February 22, 2012 16:25:09 Ali Çehreli wrote:
> On 02/22/2012 03:59 PM, Jonathan M Davis wrote:
> > On Wednesday, February 22, 2012 15:40:41 Ali Çehreli wrote:
> >> On 02/22/2012 03:16 PM, Blake Anderton wrote:
> >>> With an array the above tests work (I assume because each
> >>> operation is implicitly a new slice?).
> >> 
> >> It works because the slice itself is copied to count() and count()
> >> consumes that copy internally.
> >> 
> >> Now I see the issue here: Why does 'alias this' disable the parameter
> >> copying behavior? Why is the member slice not being copied?
> >> 
> >> This must be clarified. Is this a bug? A hole in the spec?
> > 
> > I believe that it's quite clear. Think about it. How is the template
> > instantiated? With the type that you give it. And as long as the type
> 
> passes
> 
> > the template constraint, the function will be instantiated with the exact
> > type that you gave it.
> 
> This proves that 'alias this' is something to watch out for. It makes
> our type to pass certain constraints but at the end it is still our
> object that gets passed, not the 'alias this'ed member.
> 
> The problem here has been that the original type was a class (i.e. a
> reference type). The class variable gets copied to count() and count()
> consumes the one instance of the class.
> 
> If the original code used 'struct' instead, this issue would not have
> come up, because then the member of the copy would be consumed. Sneaky! :)

Yes, but then you get all kinds of fun bugs due to the fact that your 
container is a pseudo value type. All of the instances share data as long as 
the array isn't caused to reallocate for some reason. So, you could end up 
with multiple copies affecting each other or having drastically different data, 
depending on what the code does.

But there are a variety of problems here.

Using classes for ranges makes it so that they do not work in the typically 
expected way. save is in ranges specifically for handling it, but it means that 
you have to actually _use_ it, which many algorithms should but probably 
don't, because they're only tested with ranges which are structs or arrays.

Conflating ranges and containers is a bad idea which will cause issues. They 
are distinct concepts which should be kept separate.

alias this makes it so that that type acts like the aliased type in a number 
of circumstances, but it still isn't _exactly_ that type, so it won't act 
exactly the same as the aliased type in all circumstances (templates being a 
prime example). But if you think about it, since it _is_ a different type, it 
_can't_ act like the aliased type in all circumstances. You just have to be 
well aware of what the exact effects are. But templated functions (and range-
based functions in particular) are likely to cause issues, because they'll 
compile thanks to the alias, but they won't be instantiated with the aliased 
type.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list