为什么std :: vec :: Vec实现两种Extend特性?

时间:2020-02-06 11:45:13

标签: rust lifetime

结构std::vec::Vec实现两种扩展,如指定的hereimpl<'a, T> Extend<&'a T> for Vec<T>impl<T> Extend<T> for Vec<T>。该文档指出,第一种是“扩展实现,可以在将引用推送到Vec之前从引用中复制元素”。我对Rust相当陌生,并且不确定我是否正确理解它。

我猜想第一种与C ++普通迭代器等效,第二种与C ++移动迭代器等效。

我正在尝试编写一个函数,该函数接受任何允许在后面插入i32的数据结构,因此我采用了同时实现两种Extend的参数,但是我可以t弄清楚如何指定通用参数以使其正常工作:

fn main() {
    let mut vec = std::vec::Vec::<i32>::new();
    add_stuff(&mut vec);
}

fn add_stuff<'a, Rec: std::iter::Extend<i32> + std::iter::Extend<&'a i32>>(receiver: &mut Rec) {
    let x = 1 + 4;
    receiver.extend(&[x]);
}

编译器抱怨&[x]“创建了一个仍在使用时释放的临时文件”,这是有道理的,因为'a来自函数add_stuff之外。但是,当然,我想要的是receiver.extend(&[x])从临时数组切片中复制元素并将其添加到容器的末尾,因此receiver.extend返回后将不再使用临时数组。表达我想要什么的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

add_stuff的外部开始,Rect必须能够使用其生存期在add_stuff内部给出的引用进行扩展。因此,您可能要求Rec必须能够使用排名更高的特征范围来扩展任何生命周期的引用:

fn main() {
    let mut vec = std::vec::Vec::<i32>::new();
    add_stuff(&mut vec);
}

fn add_stuff<Rec>(receiver: &mut Rec)
    where
        for<'a> Rec: std::iter::Extend<&'a i32>
{
    let x = 1 + 4;
    receiver.extend(&[x]);
}

此外,如您所见,特质界限过于狭窄。如果您在receiver内持续使用add_stuff,则其中之一应该足够。

也就是说,我只需要Extend<i32>并确保add_stuff在内部做正确的事情(如果可能):

fn add_stuff<Rec>(receiver: &mut Rec)
    where
        Rec: std::iter::Extend<i32>
{
    let x = 1 + 4;
    receiver.extend(std::iter::once(x));
}