考虑以下代码:
use std::ops;
struct Wrap<T>(T);
impl<T> Wrap<T> {
fn new(element: T) -> Self {
Wrap(element)
}
}
// implementation of other methods that makes the wrapper necessary ;-)
impl ops::Index<ops::Range<usize>> for Wrap<Vec<i8>> {
type Output = Wrap<&[i8]>;
fn index(&self, range: ops::Range<usize>) -> &Self::Output {
&Wrap::<&[i8]>::new(&self.0[range])
}
}
impl ops::Index<ops::Range<usize>> for Wrap<&[i8]> {
type Output = Wrap<&[i8]>;
fn index(&self, range: ops::Range<usize>) -> &Self::Output {
&Wrap::<&[i8]>::new(&self.0[range])
}
}
编译器指出:
error[E0106]: missing lifetime specifier
--> src/lib.rs:14:24
|
14 | type Output = Wrap<&[i8]>;
| ^ expected lifetime parameter
error[E0106]: missing lifetime specifier
--> src/lib.rs:21:45
|
21 | impl ops::Index<ops::Range<usize>> for Wrap<&[i8]> {
| ^ expected lifetime parameter
error[E0106]: missing lifetime specifier
--> src/lib.rs:22:24
|
22 | type Output = Wrap<&[i8]>;
| ^ expected lifetime parameter
我应该如何在此处设置生存期?我希望Wrap
为拥有的Vec
和借来的切片工作。最好的解决方案是什么?
答案 0 :(得分:2)
该原始设计是不可能的。 Index
期望index
方法返回对类型Self::Output
的引用:
fn index<'a>(&'a self, index: Idx) -> &'a Self::Output;
我在上面扩展了生存期,以强调返回值必须生存self
本身。当引用的值包含在被调用方中时,这是可以实现的,但对于包装的值则不是这种情况。您尝试的一种:
fn index<'a>(&'a self, range: ops::Range<usize>) -> &'a Self::Output {
&Wrap::<&[i8]>::new(&self.0[range])
}
这将创建对仅在本地存在的Wrap
对象的引用(因此不会超出'a
的寿命)。这种情况将要求使用其他特征,例如WrapIndex
,但遗憾的是,该特征不具有相同的语法糖。如果没有通用关联类型(GAT),也无法对其进行广泛推广。
pub trait WrapIndex<Idx> where
Idx: ?Sized, {
type Output: ?Sized;
fn wrap_index(&self, index: Idx) -> Wrap<&Self::Output>;
}
如果您不介意将切片类型中的所有方法公开到Wrap
中,则还可以为该包装器实现Deref
,从而免费获得索引和切片。
impl<T> Deref for Wrap<T>
where T: Deref
{
type Target = <T as Deref>::Target;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
答案 1 :(得分:0)
Cow<[T]>
可能就是您想要的:
它可以封装并提供对借入数据的不变访问权限,并在需要更改或所有权时懒惰地克隆数据
use std::borrow::Cow;
fn main() {
let w1: Cow<[i8]> = vec![1i8, 2, 3].into();
let w2: Cow<[i8]> = (&[1i8, 2, 3][..]).into();
println!("{:?}", &w1[1..2]);
println!("{:?}", &w2[1..2]);
}
这提供了适用于既有向量和借用切片的包装器,而无需重新发明轮子:)。