是一个静态阵列的前锋?

时间:2012-01-15 20:49:25

标签: d

这有效:

int[] a = [ 1, 2, 3, 4 ];
fill(a, 5);

但这不是:

int[4] a = [ 1, 2, 3, 4 ];
fill(a, 5);

我收到此错误:

  

错误:模板std.algorithm.fill(Range,Value)if(isForwardRange!(Range)&& is(typeof(range.front = filler)))与任何函数模板声明都不匹配

相反,我必须这样做才能使它与静态数组一起使用:

int[4] a = [ 1, 2, 3, 4 ];
fill(a[], 5);

请问任何人解释这种行为吗?

2 个答案:

答案 0 :(得分:7)

isForwardRange检查是否存在frontempty属性和popfront()函数

问题是popfront()需要缩小数组,因为你(应该)知道你无法调整静态数组的大小,但是可以调整静态数组的切片(本质上是普通的动态数组) (这当然不会影响静态数组)

澄清a.popfront()需要将int[4]转换为int[3],但这是不可能的

答案 1 :(得分:7)

没有。对于静态数组,isForwardRangefalse,因为它们不是有效的前向范围。他们必须拥有有效的frontemptypopFront

范围必须在迭代时进行变异。 popFront从范围中删除第一个元素,将范围的长度减少一个。静态数组不能变异。他们的元素可以是,但它们不可能。

int[5] a;
a.length = 4;

是非法的。因此,popFront不能用于静态数组,因此静态数组不能是范围。

在std.array中为数组声明了

frontemptypopFrontfrontempty将与静态数组一起使用,因为它们显式获取动态数组(不是范围),当函数采用动态数组(采用静态数组的一个片段)时,静态数组可以隐式转换为动态数组。但是,popFront不起作用,因为它需要ref动态数组。正如我所指出的那样,无论popFront的实现如何,popFront都不能用于静态数组,因为你不能改变一个范围所需的静态数组。

现在和fill一样,它需要一个前向范围,而不是一个数组。因此,IFTI(隐式函数模板实例化)将尝试使用静态数组类型(而不是动态数组类型)。由于isForwardRange对于静态数组是false,因此fill无法使用静态数组进行编译。但是,当您对静态数组进行切片时,您将传递一个动态数组,isForwardRange true。所以,它的工作原理。因为,切片指向相同的元素,并且fill改变了元素而不是数组,静态数组中的元素被fill变异。

但要小心,将静态数组切片传递给函数。只要静态数组存在,就可以了。但是一旦静态数组离开范围,它的任何切片都将无效。所以,做一些像

这样的事情
int[] foo()
{
    int[5] a = [1, 2, 3, 4, 5]
    return find(a[], 3);
}

非常糟糕。对a的引用正在逃避foo - 即其最后3个元素的一部分。

因此,如果要将一个静态数组的片段传递给函数,则需要确保没有对该数组的引用转义。但是,fill应该没问题。

相关问题