Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Rust结构中用自引用封装顺序初始化状态_Rust - Fatal编程技术网

在Rust结构中用自引用封装顺序初始化状态

在Rust结构中用自引用封装顺序初始化状态,rust,Rust,我试图定义一个结构,它可以作为RefCell中保存的Vec的迭代器: use std::slice::Iter; use std::cell::Ref; use std::cell::RefCell; struct HoldsVecInRefCell { vec_in_refcell: RefCell<Vec<i32>>, } // TODO: struct HoldsVecInRefCellIter implementing Iterator ... im

我试图定义一个结构,它可以作为
RefCell
中保存的
Vec
的迭代器:

use std::slice::Iter;
use std::cell::Ref;
use std::cell::RefCell;

struct HoldsVecInRefCell {
    vec_in_refcell: RefCell<Vec<i32>>,
}

// TODO: struct HoldsVecInRefCellIter implementing Iterator ...

impl HoldsVecInRefCell {
    fn new() -> HoldsVecInRefCell {
        HoldsVecInRefCell { vec_in_refcell: RefCell::new(Vec::new()) }
    }

    fn add_int(&self, i: i32) {
        self.vec_in_refcell.borrow_mut().push(i);
    }

    fn iter(&self) -> HoldsVecInRefCellIter {
        // TODO ...
    }
}

fn main() {
    let holds_vec = HoldsVecInRefCell::new();
    holds_vec.add_int(1);
    holds_vec.add_int(2);
    holds_vec.add_int(3);

    let mut vec_iter = holds_vec.iter();  // Under the hood: run-time borrow check

    for i in vec_iter {
        println!("{}", i);
    }
}
有没有办法定义一个实现
Iterator
的结构,该结构同时包含
Ref
(保持不变的
RefCell
借用活动)和
Iter
(保持
next()
的迭代器状态,而不是为
Vec
或任何其他容器滚动我自己的迭代器),什么时候第二个是从第一个派生出来的(并持有从第一个派生出来的引用)

我尝试了几种方法来实现这一点,但都与借用检查器相冲突。如果我把两个状态都作为裸结构成员,比如

struct HoldsVecInRefCellIter<'a> {
    vec_ref: Ref<'a, Vec<i32>>,
    vec_iter: Iter<'a, i32>,
}
然后,我引发结构的可变自借用,从而阻止从
iter()
返回它。如果试图在结构本身()中存储对结构的一部分的引用,也可能发生结构的这种自借用,这将阻止安全地移动结构的实例。相比之下,如果您能够完成初始化,它看起来像是一个结构,如
HoldsVecInRefCellIter
,在移动时会做正确的事情,因为所有内部引用都指向此结构之外的其他位置的数据

有一些技巧可以避免使用
Rc
(请参见中的示例)创建自引用,但是如果您想存储现有的
迭代器
结构(实现该结构是为了保存对底层容器的直接引用,而不是
Rc
),我不知道如何应用这些技巧

< P>作为来自C++的锈新手,这感觉起来像是一个经常出现的问题(“我在代码块中有一些复杂的状态初始化逻辑,我想抽象掉这个逻辑,并将结果状态保存在一个结构中以供使用))。
相关问题:

我们将不得不在一生中欺骗和撒谎

use std::mem;

struct HoldsVecInRefCellIter<'a> {
    vec_ref: Ref<'a, Vec<i32>>,
    vec_iter: Iter<'a, i32>, // 'a is a lie!
}

impl HoldsVecInRefCell {
    fn iter(&self) -> HoldsVecInRefCellIter {
        unsafe {
            let vec_ref = self.vec_in_refcell.borrow();
            // transmute changes the lifetime parameter on the Iter
            let vec_iter = mem::transmute(vec_ref.iter());
            HoldsVecInRefCellIter { vec_ref: vec_ref, vec_iter: vec_iter }
        }
    }
}

impl<'a> Iterator for HoldsVecInRefCellIter<'a> {
    type Item = i32;

    fn next(&mut self) -> Option<Self::Item> {
        self.vec_iter.next().cloned()
    }
}

复杂的初始化是常见的-这通常由生成器模式解决;这不是问题所在。切片的迭代器希望能够在切片存在的整个时间内保持对切片的引用;事实上,您可以添加一个
fn-borrow(&self)->Ref
方法来存储并调用
iter
,或者您可以接受一个由迭代器提供的闭包:
fn-iter(&self,f:f)
来澄清:我的意图是让迭代器返回值,而不是引用(
i32
)。我的挑战是初始化迭代器结构,它可以通过为底层容器存储
迭代器来生成值。对于这个例子,
HoldsVecInRefCellIter
可以只保存
Ref
和向量的索引,但是对于其他
Ref
我想您需要容器的
迭代器,通过这样做,基本上可以实现迭代
i32
的最终结果,尽管它无法实现抽象出
HoldsVecInRefCell
的实现细节的目标。闭包的想法很有趣——它不是一个迭代器,但它确实允许用户接收后续的
i32
s,而不知道它们是如何存储在内部的。我刚刚编辑了一个相关问题的链接,这个链接与您想要做的事情非常相似。我想你所要做的就是在答案的
into iter()
函数中调用
map(|&x | x.clone())
,以获得你想要的精确行为。
struct HoldsVecInRefCellIter<'a> {
    vec_ref: Ref<'a, Vec<i32>>,
    vec_iter: Option<Iter<'a, i32>>,
}

// ...

impl HoldsVecInRefCell {
    // ...

    fn iter(&self) -> HoldsVecInRefCellIter {
        let mut new_iter = HoldsVecInRefCellIter { vec_ref: self.vec_in_refcell.borrow(), vec_iter: None };
        new_iter.vec_iter = new_iter.vec_ref.iter();
        new_iter
    }
}
use std::mem;

struct HoldsVecInRefCellIter<'a> {
    vec_ref: Ref<'a, Vec<i32>>,
    vec_iter: Iter<'a, i32>, // 'a is a lie!
}

impl HoldsVecInRefCell {
    fn iter(&self) -> HoldsVecInRefCellIter {
        unsafe {
            let vec_ref = self.vec_in_refcell.borrow();
            // transmute changes the lifetime parameter on the Iter
            let vec_iter = mem::transmute(vec_ref.iter());
            HoldsVecInRefCellIter { vec_ref: vec_ref, vec_iter: vec_iter }
        }
    }
}

impl<'a> Iterator for HoldsVecInRefCellIter<'a> {
    type Item = i32;

    fn next(&mut self) -> Option<Self::Item> {
        self.vec_iter.next().cloned()
    }
}
impl<'a> Iterator for HoldsVecInRefCellIter<'a> {
    type Item = &'a i32;

    fn next(&mut self) -> Option<Self::Item> {
        self.vec_iter.next()
    }
}