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