数组不能被 RangeFull 索引? [英] Array cannot be indexed by RangeFull?
问题描述
考虑以下示例:
use std::ops::Index;
use std::ops::RangeFull;
fn f<T: Index<RangeFull>>(x: T) {}
fn main() {
let x: [i32; 4] = [0, 1, 2, 3];
f(x);
}
调用 f(x)
时,出现错误:
Upon calling f(x)
, I get an error:
error[E0277]: the type `[i32; 4]` cannot be indexed by `std::ops::RangeFull`
--> src/main.rs:8:5
|
8 | f(x);
| ^ `[i32; 4]` cannot be indexed by `std::ops::RangeFull`
|
= help: the trait `std::ops::Index<std::ops::RangeFull>` is not implemented for `[i32; 4]`
note: required by `f`
--> src/main.rs:4:1
|
4 | fn f<T: Index<RangeFull>>(x: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我很困惑.我显然可以写,例如,let y = x[..];
.这不意味着用 RangeFull
索引 x
吗?数组在这方面有什么特别之处吗?
I am confused. I can obviously write, for example, let y = x[..];
. Does this not mean indexing x
with RangeFull
? Are arrays somehow special in this regard?
推荐答案
正如你在 原始数组类型的文档,Index<…>
不是直接为数组实现的.这部分是因为目前不可能为所有数组大小提供全面的实现,但主要是因为没有必要;切片的实现足以满足大多数用途.
As you can see in the documentation for the primitive array type, Index<…>
is not directly implemented for arrays. This is partly because it would currently be impossible to provide blanket implementations for all array sizes, but mainly because it's not necessary; the implementation for slices is sufficient for most purposes.
表达式 x[..]
被编译器翻译成 *std::ops::Index::index(&x, ..)
,反过来,根据通常的方法调用语义一>.由于数组没有Index
的实现,编译器反复对&x
进行解引用,最后执行unsized强制转换,最终找到[i32]
的 >Index
The expression x[..]
is translated to *std::ops::Index::index(&x, ..)
by the compiler, which in turn is evaluated according to the usual method call semantics. Since there is no implementation of Index<RangeFull>
for arrays, the compiler repeatedly dereferences &x
and performs an unsized coercion at the end, eventually finding the implementation of Index<RangeFull>
for [i32]
.
调用泛型函数的过程(例如您示例中的 f()
)与方法调用语义不同.编译器首先根据您传递的参数推断 T
是什么;在这种情况下,T
被推断为 [i32;4]
.在下一步中,编译器验证 T
是否满足特征边界,如果不满足,您会收到一条错误消息.
The process of calling a generic function, like f()
in your example, is different from method call semantics. The compiler first infers what T
is based on the argument you are passing; in this case T
is inferred to be [i32; 4]
. In the next step, the compiler verifies whether T
satisfies the trait bounds, and since it doesn't, you get an error message.
如果我们想让你的代码工作,我们需要确保将切片传递给 f()
.由于切片没有大小,我们需要通过引用传递它,所以我们需要像这样定义f()
:
If we want to make your code work, we need to make sure to pass a slice to f()
. Since a slice is unsized, we need to pass it by reference, so we need to define f()
like this:
fn f<T: ?Sized + Index<RangeFull>>(_: &T) {}
?Sized
是必要的,因为类型参数接收一个隐式的 Sized
绑定.在调用 f()
时,我们需要确保 T
实际上被推断为 [i32]
而不是 [i32;4]
.为此,我们可以明确指定T
The ?Sized
is necessary since type parameters receive an implicit Sized
bound. When calling f()
, we need to make sure T
is actually inferred as [i32]
rather than [i32; 4]
. To this end, we can either explicitly specify T
f::<[_]>(&x);
或者在传递参数之前显式执行 unsized 转换,以便编译器推断所需的类型:
or explicitly perform the unsized conversion before passing the argument, so the compiler infers the desired type:
f(&x as &[_]);
f(&x[..])
这篇关于数组不能被 RangeFull 索引?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!