Rust:从 std::Rc 智能指针向量实现迭代器

如何解决Rust:从 std::Rc 智能指针向量实现迭代器

我开始使用 Rust,但我已经面临数据所有权问题。

我想实现一个名为 Port<T> 的通用结构,它具有值向量 Vec<T>。此外,这个结构体有一个指向相同类型的其他结构体的引用计数指针向量,Vec<Rc<Port<T>>>:

use std::slice::Iter;
use std::rc::Rc;

pub struct Port<T> {
    values: Vec<T>,ports: Vec<Rc<Port<T>>>,}

想法如下:有多个 Port<T> 类型的结构。您可以将 T 类型的值添加到给定端口。每个端口将这些值存储在其 values 属性中。但是,可以使用引用计数指针将一个端口“链接”到其他端口:

impl <T> Port<T> {
    pub fn new() -> Self {
        Self { values: vec![],ports: vec![] }
    }

    pub fn add_value(&mut self,value: T) {
        self.values.push(value);
    }

    pub fn chain_port(&mut self,port: Rc<Port<T>>) {
        if !port.is_empty() {
            self.ports.push(port)
        }
    }

    pub fn is_empty(&self) -> bool {
        self.values.is_empty() || self.ports.is_empty()
    }

    pub fn clear(&mut self) {
        self.values.clear();
        self.ports.clear();
    }
}

至此,代码编译通过。现在,我想为一个端口实现一个迭代器,该迭代器返回对此端口拥有的值的引用,以及对每个链接端口的迭代器生成的值的引用:

pub struct PortIterator<'a,T> {
    values: Iter<'a,T>,// Iterates over values owned by Port<T>
    port: Option<Box<PortIterator<'a,T>>>,// Pointer to current port iterator
    ports: Vec<Rc<Port<T>>>,// Pointers to remaining chained ports
}

// Note that the iterator is created from an immutable reference to Port<T>
impl<'a,T: 'a> IntoIterator for &'a Port<T> {
    type Item = &'a T;  // the iterator returns references to values
    type IntoIter = PortIterator<'a,T>;

    fn into_iter(self) -> Self::IntoIter {
        // We clone all the reference-counting pointers so the iterator owns them
        let mut ports = vec![];
        for port in self.ports.iter() {
            ports.push(port.clone())
        }
        PortIterator {values: self.values.iter(),port: None,ports}
    }
}

现在,让我们为 Iterator 定义 PortIterator 特征:

impl <'a,T: 'a> Iterator for PortIterator<'a,T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        // We first iterate over values of the original port
        if let Some(v) = self.values.next() {
            return Some(v)
        }
        // If the first iterable is done,we try to iterate over a chained port
        if let Some(port) = &mut self.port {
            if let Some(v) = port.next() {
                return Some(v)
            }
        }
        // if the chained port is over,we try to consume the next chained port
        if let Some(port) = self.ports.get(self.next_port) {
            self.next_port += 1;
            self.port = Some(Box::new(port.as_ref().into_iter()));
            return self.next()
        }
        None
    }
}

现在,程序无法编译。问题似乎出在第三个 if let 块中,并且与生命周期有关。这是编译器所说的:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/modeling/port.rs:69:40
   |
69 |         if let Some(port) = self.ports.get(self.next_port) {
   |                                        ^^^
   |
note: first,the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 57:5...
  --> src/modeling/port.rs:57:5
   |
57 |     fn next(&mut self) -> Option<Self::Item> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/modeling/port.rs:69:29
   |
69 |         if let Some(port) = self.ports.get(self.next_port) {
   |                             ^^^^^^^^^^
note: but,the lifetime must be valid for the lifetime `'a` as defined on the impl at 54:7...
  --> src/modeling/port.rs:54:7
   |
54 | impl <'a,T> {
   |       ^^
note: ...so that the expression is assignable
  --> src/modeling/port.rs:71:25
   |
71 |             self.port = Some(Box::new(port.as_ref().into_iter()));
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected `Option<Box<PortIterator<'a,_>>>`
              found `Option<Box<PortIterator<'_,_>>>`

我不知道如何处理这个问题。我一直在尝试其他选项和实现,但我一直在兜圈子。

解决方法

我认为有更简单的方法可以实现您想要实现的目标。让我们从小处着手:您的 Port<T> 需要一个 iter(&self) 方法,该方法返回一个分发 &T 项的迭代器:

pub fn iter(&self) -> impl Iterator<Item = &T> {
    // ...
}

此函数需要通过 self.values 链接迭代器,即 self.values.iter() 与链接端口上的迭代器。你想写的东西是这样的:

pub fn iter(&self) -> impl Iterator<Item = &T> {
    self.values
        .iter()
        .chain(self.ports.iter().flat_map(|p| p.iter()))
}

然而,这不会编译,因为编译器抱怨“递归不透明类型”。这是因为 p.iter() 的类型与我们的 impl Iterator<...> 完全相同,因此它必须包含自身。这在概念上与您在构建 PortIterator 时遇到的问题相同,您通过装箱链接的 PortIterator 解决了该问题。我们可以用同样的方式解决它,通过装箱内部迭代器并动态调度它:

pub fn iter(&self) -> impl Iterator<Item = &T> {
    self.values.iter().chain(
        self.ports
            .iter()
            .flat_map(|p| Box::new(p.iter()) as Box<dyn Iterator<Item = &T>>),)
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?