我想编写一个具有诸如 foo(&self) -> &T
之类的方法的特征,并将其实现为具体类型而不是引用。这是我尝试过的,但我无法让它工作:
trait GetRef<'a> {
fn get(&self) -> &'a u8;
}
// U8Ref works fine
struct U8Ref<'a> {
data: &'a u8
}
impl<'a> GetRef<'a> for U8Ref<'a> {
fn get(&self) -> &'a u8 {
self.data
}
}
struct U80 { data: u8 }
struct U81 { data: u8 }
struct U82 { data: u8 }
struct U83 { data: u8 }
// works, but is not exactly what I want (API changes, and does not work on
// &mut U80, see main() below)
impl<'a> GetRef<'a> for &'a U80 {
fn get(&self) -> &'a u8 {
&self.data
}
}
impl<'a> GetRef<'a> for U81 {
fn get(&self) -> &'a u8 {
// E0495: cannot infer an appropriate lifetime for lifetime parameter
// in generic type due to conflicting requirements
&self.data
}
}
impl<'a> GetRef<'a> for U82 {
//E0308: lifetime mismatch
fn get(&'a self) -> &'a u8 {
&self.data
}
}
impl<'a> GetRef<'a> for &'a mut U83 {
fn get(&self) -> &'a u8 {
// again E0495
&self.data
}
}
fn main() {
let u0 = U80 {data :0};
// works
(&u0).get();
// no method named `get` found for type `U80` in the current scope
u0.get();
// no method named `get` found for type `&mut U80` in the current scope
(&mut u0).get();
}
最佳答案
你的特质的实现需要限制所涉及的生命周期。对于您的 U8Ref
情况,生命周期将比 self
长,但在 U80
和类似情况下,它们将是相等的。
该特征需要有两个生命周期作为输入才能表达这一点,所以让我们将 self
生命周期添加为 的
:
trait GetRef<'a, 's> {
fn get(&'s self) -> &'a u8;
}
现在这些都是明确的,我们可以编写impl
。首先,对于持有引用的人:
struct U8Ref<'a> {
data: &'a u8
}
// Straightforward; we can separate the self and return reference lifetimes.
impl<'a, 's> GetRef<'a, 's> for U8Ref<'a> {
fn get(&'s self) -> &'a u8 {
self.data
}
}
现在,对于之前更困难的情况,我们可以明确告诉编译器生命周期是相同的:
struct U80 { data: u8 }
// The impl is only valid when &self has the same lifetime as the &u8 returned.
impl<'a> GetRef<'a, 'a> for U80 {
fn get(&'a self) -> &'a u8 {
&self.data
}
}
并用它来检查它的编译:
fn main() {
let mut u0 = U80 {data :0};
let uval: u8 = 7;
let ur0 = U8Ref { data: &uval };
ur0.get();
(&u0).get();
u0.get();
(&mut u0).get();
{
// Check that it works when U8Ref's reference outlives itself.
let v = 0u8;
let u: &u8;
{
let r = U8Ref { data: &v };
u = r.get();
}
println!("{}", u);
}
}
关于rust - 如何编写一个具有返回引用的方法的特征并正确实现它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40449512/