混合Vec中参考文献的生命周期

时间:2017-04-12 02:25:03

标签: reference rust lifetime

我正在尝试从Vec<&'b Color>生成Vec<&'a Color>

impl <'a> Canvas<'a> {
    pub fn modify<'b>(&self, update: Update) -> Canvas<'b> {
        let x  = update.x;
        let y  = update.y;
        let colors: Vec<&'b Color> = self.colors.iter().enumerate().map(move |(index, color)| {
                if index == self.width * y + x { update.color } else { color }
            })
            .collect();
        Canvas { width: self.width, height: self.height, colors: colors }
    }
}

但是,我收到以下错误:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/canvas.rs:51:50
   |
51 |         let colors: Vec<&'b Color> = self.colors.iter().enumerate().map(move |(index, color)| {
   |                                                  ^^^^

如何创建Vec种颜色,只有一种颜色具有生命期'a,其余颜色的生命期为'b

如果需要,相关定义如下:

#[derive(Debug, PartialEq, Eq)]
pub enum Color {
    White,
    Red,
    Blue,
    Green,
    Purple,
    Orange
}

pub struct Update<'a> {
    color: &'a Color,
    x: usize,
    y: usize
}

pub struct Canvas<'a> {
    width: usize,
    height: usize,
    colors: Vec<&'a Color>
}

1 个答案:

答案 0 :(得分:3)

  

如何创建Vec种颜色,只有一种颜色具有生命期'a,其余颜色的生命期为'b

不能。生命周期是泛型,就像拥有“Vec<T>一样没有意义,除了T之外的所有人都是String类型,剩下的T是类型bool“,生命周期没有意义。

你能做的就是统一一生:

impl<'a> Canvas<'a> {
    pub fn modify(&self, update: Update<'a>) -> Canvas<'a> {
        let x = update.x;
        let y = update.y;
        let colors = self.colors
            .iter()
            .enumerate()
            .map(move |(index, color)| if index == self.width * y + x {
                     update.color
                 } else {
                     color
                 })
            .collect();
        Canvas {
            width: self.width,
            height: self.height,
            colors: colors,
        }
    }
}

在这里,我们已经说过update.color生命周期和所包含引用的生命周期有一个交集,这就是结果的生命周期。

另一种针对固定类型集的异构集合的常见解决方案是为每个类型引入一个带变体的枚举:

pub enum Thing<'a, 'b>  {
    A(&'a Color),
    B(&'b Color),
}

impl<'a> Canvas<'a> {
    pub fn modify<'b>(&self, update: Update<'b>) -> Vec<Thing<'a, 'b>> {
        let x = update.x;
        let y = update.y;
        self.colors
            .iter()
            .enumerate()
            .map(move |(index, color)| if index == self.width * y + x {
                     Thing::B(update.color)
                 } else {
                     Thing::A(color)
                 })
            .collect()
    }
}