Iterator字段的生命周期

时间:2014-11-15 18:33:01

标签: iterator rust

在学习这种新的迷人语言时,我编写了这段代码,输出0到10乘以3:

pub struct Multiplier {
    factor : int,
    current : int
}
impl Multiplier {
    pub fn new(factor : int) -> Multiplier {
        Multiplier {
            factor: factor,
            current: 0
        }
    }
}
impl Iterator<int> for Multiplier {
    fn next(&mut self) -> Option<int> {
        if self.current > 10 {
            None
        }
        else {
            let current = self.current;
            self.current += 1;
            Some(current * self.factor)
        }
    }
}

struct Holder {
    x : Multiplier
}
impl Holder {
    pub fn new(factor : int) -> Holder {
        Holder {
            x : Multiplier::new(factor)
        }
    }

    fn get_iterator(&self) -> Multiplier {
        self.x
    }
}

fn main() {
    let mut three_multiplier = Holder::new(3).get_iterator();
    for item in three_multiplier {
        println!("{}", item);
    }
}

如果我从此

更改Holder
struct Holder {
    x : Multiplier
}

到此:

struct Holder {
    x : Iterator<int>
}

我收到了编译警告:

<anon>:27:9: 27:22 error: explicit lifetime bound required
<anon>:27     x : Iterator<int>
                  ^~~~~~~~~~~~~

有人可以解释为什么更改字段类型需要明确的生命周期吗?我知道如何标记生命周期,但我不确定编译器为什么要我这样做。

1 个答案:

答案 0 :(得分:3)

您可以通过以下方式添加生命周期:

struct Holder<'a> {
    x: Iterator<int>+'a
}

但是请注意,Holder结构是 unsized ,因为它包含一个未标注的特征对象。这严重限制了您可以对类型执行的操作:例如,您无法直接返回Holder

您可以通过Holder接受类型参数来解决此问题:

struct Holder<T> where T: Iterator<int> {
    x : T
}

让我们更改get_iterator以使用类型参数:

impl<T> Holder<T> where T: Iterator<int>+Copy {
    fn get_iterator(&self) -> T {
        self.x
    }
}

注意:我在此处添加了Copy,因为get_iterator当前返回了副本。您可以通过get_iterator代替&T来避免约束。

对于new,您必须完全重新设计它。如果我们保持原样,如果我们将其称为Holder::new,则编译器会给出错误,因为Holder现在有一个类型参数,并且编译器无法推断类型,因为new没有&#39}。使用任何。为了解决这个问题,我们可以通过使用特征提供构造函数来使new泛型:

trait FactorCtor {
    fn new(factor: int) -> Self;
}

然后更改new以使用该特征:

impl<T> Holder<T> where T: Iterator<int>+FactorCtor {
    pub fn new(factor : int) -> Holder<T> {
        Holder {
            x : FactorCtor::new(factor)
        }
    }
}

因为我们在此程序中只有FactorCtor的一个实现,所以编译器在调用T时设法推断Holder::new。如果我们添加另一个实现,例如Adder

pub struct Adder {
    factor : int,
    current : int
}
impl FactorCtor for Adder {
    fn new(factor: int) -> Adder {
        Adder {
            factor: factor,
            current: 0
        }
    }
}
impl Iterator<int> for Adder {
    fn next(&mut self) -> Option<int> {
        if self.current > 10 {
            None
        }
        else {
            let current = self.current;
            self.current += 1;
            Some(current + self.factor)
        }
    }
}

然后我们得到一个编译器错误:

<anon>:72:9: 72:29 error: unable to infer enough type information about `_`; type annotations required
<anon>:72     let mut three_multiplier = Holder::new(3).get_iterator();
                  ^~~~~~~~~~~~~~~~~~~~

我们可以通过明确指定T来解决此问题:

fn main() {
    let mut three_multiplier = Holder::<Multiplier>::new(3).get_iterator();
    for item in three_multiplier {
        println!("{}", item);
    }
}