数组不能被 RangeFull 索引? [英] Array cannot be indexed by RangeFull?

查看:28
本文介绍了数组不能被 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆