D 静态阵列是否为正向范围?
这项工作:D 静态阵列是否为正向范围?,d,D,这项工作: int[] a = [ 1, 2, 3, 4 ]; fill(a, 5); 但这并不是: int[4] a = [ 1, 2, 3, 4 ]; fill(a, 5); 我得到了这个错误: 错误:如果(isForwardRange!(Range)&&is(typeof(Range.front=filler)))与任何函数模板声明不匹配,则模板std.algorithm.fill(范围,值) 相反,我必须这样做才能使它与静态阵列一起工作: int[4] a = [ 1, 2, 3,
int[] a = [ 1, 2, 3, 4 ];
fill(a, 5);
但这并不是:
int[4] a = [ 1, 2, 3, 4 ];
fill(a, 5);
我得到了这个错误:
错误:如果(isForwardRange!(Range)&&is(typeof(Range.front=filler)))与任何函数模板声明不匹配,则模板std.algorithm.fill(范围,值)
相反,我必须这样做才能使它与静态阵列一起工作:
int[4] a = [ 1, 2, 3, 4 ];
fill(a[], 5);
有人能解释一下这种行为吗?
isForwardRange
检查是否存在front
、empty
属性和popfront()
函数
问题是popfront()
需要收缩数组,因为您(应该)知道不能调整静态数组的大小,但可以调整静态数组(基本上是正常的动态数组)的一部分大小(这当然不会影响静态数组)
要澄清
a.popfront()
需要将a从int[4]
转换为int[3]
,但这是不可能的否。isForwardRange
对于静态数组是false
,因为它们不是有效的前向范围。它们必须具有有效的前端
,空的
,以及popFront
范围在迭代时必须进行变异popFront
从范围中删除第一个元素,将范围长度减少一个。静态数组不能进行变异。它们的元素可以是,但不能是
int[5] a;
a.length = 4;
这是违法的。因此,popFront
无法使用静态数组,因此静态数组不能是范围
front
、empty
和popFront
是为std.array中的数组声明的,而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
,但是应该可以。我说的必须使用array
和SList
进行切片是否正确?这似乎是一个设计缺陷。这并不是一个真正的设计缺陷动态数组是范围的一种奇怪的特殊情况。但由于它们是当前最常见的情况,我们已经习惯了。容器必须隐式转换为IFTI的切片类型,以便在传递给函数时不需要显式切片,这将使传递CONTAIN变得更加困难rs到模板化函数。我不确定通常使用IFTI自动切片所有可切片类型是否是一个好主意,即使只是在处理范围时也是如此。您可以这样想。容器(包括静态数组)需要切片才能在其上获得一个范围。因此,如果您希望任何re都在其上获得一个范围ason-包括传递给基于范围的函数-您必须显式地对它们进行切片。但是动态数组已经是范围而不是容器,因此切片是不必要的。那么为什么fill
需要一个范围,为什么它不需要一个可切片的通用容器/数组?在内部它可以切片并获得它所需要的范围需要。这样的错误将不会发生。@Daevius它没有任何冗余。动态数组是一个范围。静态数组不是。此外,动态数组是一个切片,而静态数组不是。静态数组拥有内存。动态数组不拥有内存。您显式地请求对静态数组进行切片,以便可以获取数据一个动态数组。你得到它的一部分就像你得到一个容器的一部分一样。如果我把静态数组当作动态数组来对待,那么当你真正想要一个静态数组时,把静态数组作为静态数组传递给模板函数会更困难。也就是说,popfront的参数和返回类型必须是相同的?popfront
是一个更改此
参数的函数,因此front
属性更改(指向“next”元素)(可能是empty
属性)。这在静态数组中是不可能的,因为长度是在编译时设置的,并且是类型的一部分。