考虑以下示例:
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)
时出现错误:
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[..];
。这是否意味着用x
索引RangeFull
?数组在这方面有什么特殊之处吗?
答案 0 :(得分:2)
如您在documentation for the primitive array type中所见,select r.*
from (select r.*,
lag(stateid) over (partition by idcont order by day_id) as prev_stateid,
first_value(stateid) over (partition by idcont order by day_id desc) as last_stateid
from reftable r
) r
where stateid = last_stateid and (prev_stateid is null or prev_stateid <> stateid);
并非直接用于数组。部分原因是目前不可能为所有阵列大小提供统一的实现,但主要是因为没有必要。对于大多数用途而言,切片的实施就足够了。
表达式Index<…>
由编译器翻译为x[..]
,编译器又根据usual method call semantics对其求值。由于没有针对数组的*std::ops::Index::index(&x, ..)
的实现,因此编译器反复取消引用Index<RangeFull>
并在最后执行不定大小的强制转换,最终为&x
找到Index<RangeFull>
的实现。 / p>
调用泛型函数(例如您的示例中的[i32]
)的过程与方法调用语义不同。编译器首先根据您传递的参数来推断f()
的含义。在这种情况下,T
被推断为T
。在下一步中,编译器将验证[i32; 4]
是否满足特征范围,并且由于不满足,您会收到一条错误消息。
如果我们要使您的代码正常工作,则需要确保将切片传递给T
。由于切片未调整大小,因此需要通过引用传递它,因此我们需要像这样定义f()
:
f()
fn f<T: ?Sized + Index<RangeFull>>(_: &T) {}
是必需的,因为类型参数接收隐式的?Sized
边界。调用Sized
时,我们需要确保实际上将f()
推断为T
而不是[i32]
。为此,我们可以显式指定[i32; 4]
T
或在传递参数之前显式执行未调整大小的转换,因此编译器会推断出所需的类型:
f::<[_]>(&x);