这有效:
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);
请问任何人解释这种行为吗?
答案 0 :(得分:7)
isForwardRange
检查是否存在front
,empty
属性和popfront()
函数
问题是popfront()
需要缩小数组,因为你(应该)知道你无法调整静态数组的大小,但是可以调整静态数组的切片(本质上是普通的动态数组) (这当然不会影响静态数组)
澄清a.popfront()
需要将int[4]
转换为int[3]
,但这是不可能的
答案 1 :(得分:7)
没有。对于静态数组,isForwardRange
为false
,因为它们不是有效的前向范围。他们必须拥有有效的front
,empty
和popFront
。
范围必须在迭代时进行变异。 popFront
从范围中删除第一个元素,将范围的长度减少一个。静态数组不能变异。他们的元素可以是,但它们不可能。
int[5] a;
a.length = 4;
是非法的。因此,popFront
不能用于静态数组,因此静态数组不能是范围。
front
,empty
和popFront
,front
和empty
将与静态数组一起使用,因为它们显式获取动态数组(不是范围),当函数采用动态数组(采用静态数组的一个片段)时,静态数组可以隐式转换为动态数组。但是,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
应该没问题。