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