trait SliceLike {
type Item;
/// Computes and returns (owned) the first item in a collection.
fn first_item(&self) -> Self::Item;
}
请注意
Item
类型是关联的类型;我想要每一种
SliceLike
要具有唯一的元素类型。
下面是一个全面实施的尝试:
use std::ops::Deref;
impl<T: Clone, U: Deref<Target = [T]>> SliceLike for U {
type Item = T;
fn first_item(&self) -> Self::Item {
self[0].clone()
}
}
let data: Vec<usize> = vec![3, 4];
assert_eq!(data.first_item(), 3);
let data: &[usize] = &[3, 4];
assert_eq!(data.first_item(), 3);
let data: Box<[usize]> = Box::new([3, 4]);
assert_eq!(data.first_item(), 3);
let data: Rc<[usize]> = Rc::new([3, 4]);
assert_eq!((&data).first_item(), 3);
它还编译并运行:
fn stub(x: &[usize]) -> usize {
x.first_item()
}
let data: [usize; 2] = [3, 4];
assert_eq!(stub(&data), 3);
assert_eq!(stub(&[3, 4]), 3);
stub()
let data: [usize; 2] = [3, 4];
assert_eq!(data.first_item(), 3); // Fails.
assert_eq!([3, 4].first_item(), 3); // Fails.
总括实现使用
Deref
编译器自身用于将其他类型转换为片的特性。它将捕获所有行为类似于切片的第三方类型。
error[E0599]: no method named `first_item` found for type `[usize; 2]` in the current scope
--> src/lib.rs:20:21
|
20 | assert_eq!(data.first_item(), 3); // Fails.
| ^^^^^^^^^^
|
= note: the method `first_item` exists but the following trait bounds were not satisfied:
`[usize; 2] : SliceLike`
`[usize] : SliceLike`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `first_item`, perhaps you need to implement it:
candidate #1: `SliceLike`
在里面
take 1
对于这个问题,有人建议我使用
AsRef
德里夫
. 该解决方案在这里不起作用,因为某些类型可能会实现
AsRef
我想我明白发生了什么。每种类型
T
有一种独特的类型
<T as Deref>::Target
. 什么时候
T
&[usize; 2]
目标是
[usize; 2]
不
[usize]
. 编译器能够强制
&[T; 2]
到
&[T]
如果我明确要求,例如使用
let
或
,但如果我不这样做,那么就无法确定是否需要强制。
但这是令人沮丧的:对于一个人来说,失败调用的意图是什么是显而易见的,并且编译器知道需要做什么
Vec<usize>
,
Box<[usize]>
,
Rc<[usize]>
,
&[usize]
[使用;2]
有没有方便的写作方法
first()
所以最后两个电话也能用?如果没有,是否有语法要求编译器强制
&
到
&[使用]
内联,
不用
或
存根()
?
Playground