Alias this with array can only be used once

Jonathan M Davis jmdavisProg at gmx.com
Wed Feb 22 15:59:09 PST 2012


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. What does the template constraint do? In this case
it's

if(isInputRange!Range && is(typeof(binaryFun!pred(r.front, value)) == bool))

where isInputRange is

template isInputRange(R)
{
 enum bool isInputRange = is(typeof(
 {
 R r = void; // can define a range object
 if (r.empty) {} // can test for empty
 r.popFront(); // can invoke popFront()
 auto h = r.front; // can get the front of the range
 }));
}

Well, because of the alias, r.front will grab the front on the array (as there 
is no front on the container), and the second part will compile and be 
considered true. In the case of isInputRange, it becomes

template isInputRange(R)
{
 enum bool isInputRange = is(typeof(
 {
 ArrayContainer r = void; // can define a range object
 if (r.empty) {} // can test for empty
 r.popFront(); // can invoke popFront()
 auto h = r.front; // can get the front of the range
 }));
}

Naturally, the declaration of ArrayContainer succeeds, and then all of the 
subsequent functions just end up using alias this with the array. So, the 
result is true, and so isInputRange is true, and ArrayContainer passes count's 
template constraint. And so, count is instantiated with ArrayContainer, not 
int[].

I don't see anything ambiguous about that. You asked the compiler to 
instantiate count with ArrayContainer, not int[], and so that's what it did. 
You could explicitly instantiate it with int[] if you wanted to, though you 
might as well just slice the ArrayContainer (and thus the int[]) and get an 
int[] that way.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list