在拥有盒装特征的结构上实现Deref

时间:2015-06-05 18:20:10

标签: rust

我想在拥有盒装特征的结构上实现DerefDefrefMut,例如:

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
    }
}

无法使用以下错误进行编译:

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     }

如果我将Box<Quack>替换为Box<String>(或类似的类型),则可行。问题是Quack是一个特征。但我不确定为什么会产生错误消息。有什么想法吗?

我的问题类似于another SO question,但不完全相同。在该问题中,struct具有类型参数,其中trait为约束。而在我的问题中,没有类型参数。

我不想混淆这些问题,但我的申请中需要Box<Quack>这是一个很好的理由。即我无法用类型参数替换Quack。如果您关心,原因是discussed further in another SO question

2 个答案:

答案 0 :(得分:7)

如有疑问,请添加更多生命周期注释:

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
    }
}

答案 1 :(得分:1)

根据Brian的回答和Shepmaster的解释,我更新了我的代码如下。我还简化了QuackWrap结构。 (这不是必须的,但它的风格可能比以前更好。)

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
    }
}

QuackWrapderef实现中,可能有一种更简洁的方法来解构deref_mut。其中一些比较模糊的语法规则让我望而却步。但是现在这很好。