I'd like to implement Deref
and DefrefMut
on a struct that owns a boxed trait, eg:
use std::ops::{Deref, DerefMut};
trait Quack {
fn quack(&self);
}
struct QuackWrap {
value: Box<Quack>
}
impl Deref for QuackWrap {
type Target = Box<Quack>;
fn deref<'a>(&'a self) -> &'a Box<Quack> {
&self.value
}
}
impl DerefMut for QuackWrap {
fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack> {
&mut self.value
}
}
This fails to compile with the following error:
src/main.rs:14:5: 16:6 error: method `deref` has an incompatible type for trait: expected bound lifetime parameter 'a, found concrete lifetime [E0053]
src/main.rs:14 fn deref<'a>(&'a self) -> &'a Box<Quack> {
src/main.rs:15 &self.value
src/main.rs:16 }
src/main.rs:20:5: 22:6 error: method `deref_mut` has an incompatible type for trait: expected bound lifetime parameter 'a, found concrete lifetime [E0053]
src/main.rs:20 fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack> {
src/main.rs:21 &mut self.value
src/main.rs:22 }
If I replace Box<Quack>
with Box<String>
(or a similar type), it works. The problem is that Quack
is a trait. But I'm not sure why that generated the error message it did. Any ideas?
My question is similar to another SO question , but not quite the same. In that question, the struct has a type parameter with the trait as a constraint. Whereas in my question, there is no type parameter.
I don't want to confuse the issues, but there's a good reason that I need Box<Quack>
in my application. Ie I can't replace Quack
with a type parameter. In case you care, the reason is discussed further in another SO question .
When in doubt, add more lifetime annotations:
use std::ops::{Deref, DerefMut};
trait Quack {
fn quack(&self);
}
struct QuackWrap<'b> {
value: Box<Quack + 'b>
}
impl<'b> Deref for QuackWrap<'b>{
type Target = Box<Quack + 'b>;
fn deref<'a>(&'a self) -> &'a Box<Quack + 'b> {
&self.value
}
}
impl<'b> DerefMut for QuackWrap<'b> {
fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack + 'b> {
&mut self.value
}
}
Based on Brian's answer and Shepmaster's explanation, I updated my code as follow. I also simplified the QuackWrap
struct. (That wasn't strictly necessary, but it's arguably better style than what I was doing before.)
use std::ops::{Deref, DerefMut};
trait Quack {
fn quack(&self);
}
struct QuackWrap(Box<Quack>);
impl Deref for QuackWrap {
type Target = Box<Quack + 'static>;
fn deref<'a>(&'a self) -> &'a Box<Quack + 'static> {
let QuackWrap(ref v) = *self;
v
}
}
impl DerefMut for QuackWrap {
fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack + 'static> {
let QuackWrap(ref mut v) = *self;
v
}
}
There may be a more concise way to destructure QuackWrap
in the deref
and deref_mut
implementations. Some of those more obscure syntax rules elude me. But for now this is fine.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.