我正在尝试在我的枚举上实现
Index
,以便我可以在为自定义类型实现切片之后获取它的切片(具有切片内部值的相同变体的枚举)。但是因为我的枚举有不同类型的变体,所以我无法让它工作:
pub enum GlkArray<'a> {
U8(&'a mut [u8]),
U32(&'a mut [u32]),
}
impl<'a, Idx> Index<Idx> for GlkArray<'a>
where Idx: SliceIndex<[usize]>
{
type Output = GlkArray<'a>;
fn index(&self, index: Idx) -> &Self::Output {
match self {
GlkArray::U8(buf) => &GlkArray::U8(&mut buf[index]),
GlkArray::U32(buf) => &GlkArray::U32(&mut buf[index]),
}
}
}
这会导致这些错误:
error[E0277]: the type `[u8]` cannot be indexed by `Idx`
--> remglk/src/glkapi/arrays.rs:117:53
|
117 | GlkArray::U8(buf) => &GlkArray::U8(&buf[index]),
| ^^^^^ slice indices are of type `usize` or ranges of `usize`
|
= note: required for `[u8]` to implement `Index<Idx>`
help: consider further restricting this bound
|
112 | where Idx: SliceIndex<[usize]> + std::slice::SliceIndex<[u8]>
| ++++++++++++++++++++++++++++++
error[E0277]: the type `[u32]` cannot be indexed by `Idx`
--> remglk/src/glkapi/arrays.rs:118:55
|
118 | GlkArray::U32(buf) => &GlkArray::U32(&buf[index]),
| ^^^^^ slice indices are of type `usize` or ranges of `usize`
|
= note: required for `[u32]` to implement `Index<Idx>`
help: consider further restricting this bound
|
112 | where Idx: SliceIndex<[usize]> + std::slice::SliceIndex<[u32]>
| +++++++++++++++++++++++++++++++
我有点理解
SliceIndex
希望在具体类型上定义,但我不确定在这种情况下该怎么做。是的,您不知道枚举从外部有什么变体,但它返回另一个封装的枚举,所以我希望没关系。
有什么想法需要如何定义
Idx
,或者我可以做什么的其他建议吗?
不幸的是,您无法为此类型实现
Index
,因为它需要从 &mut
引用后面生成新的 &
引用,这是不可能的。
即使无法正确实现
Index
,仍然可以通过恐慌的IndexMut
实现来实现Index
,但由于生命周期和所有权问题,IndexMut
也是不可能的。当您可变地重新借用切片时,它必须生成具有新生命周期的切片:
let mut x = [1, 2, 3];
// We'll say this reference has lifetime 'a
let slice = &mut x[..];
// This one has a new lifetime that's distinct from 'a
let slice2 = &mut slice[1..];
这意味着您无法从
GlkArray<'a>
返回 IndexMut::index_mut
。并且该特征的编写方式使得无法指定 GlkArray
的工作寿命。
此外,您无法返回对临时值的引用。这意味着返回
&mut GlkArray
不起作用,因为您必须在函数内创建一个新的 GlkArray
。这也适用于Index
。
有一种方法可以解决这两个问题,那就是修改原始的
GlkArray
并返回对其的引用。但这作为索引的副作用可能是不可接受的。
相反,您可以编写自己的索引函数。您将无法使用索引运算符
[_]
,但它可以正常工作。
impl GlkArray<'_> {
// The return of this function cannot be Self
pub fn get_mut<'a, I>(&'a mut self, index: I) -> Option<GlkArray<'a>>
where
I: SliceIndex<[u8], Output = [u8]> + SliceIndex<[u32], Output = [u32]>,
{
match self {
Self::U8(slice) => slice.get_mut(index).map(GlkArray::U8),
Self::U32(slice) => slice.get_mut(index).map(GlkArray::U32),
}
}
}