如何返回一个引用RefCell内部内容的迭代器?

时间:2017-03-08 16:20:34

标签: reference rust iterator interior-mutability

我正在尝试创建一个方法,该方法返回RTCPeerConnectionHashMap的{​​{1}}值的迭代器,但我错误地{{1} } RefCell返回的内容不足以让迭代器从方法返回。这是我的代码:

Ref

编译错误:

RefCell::borrow

How do I return a reference to something inside a RefCell without breaking encapsulation?建议创建一个包含use std::rc::Rc; use std::cell::RefCell; use std::collections::HashMap; use std::collections::hash_map::Values; struct Foo { map: Rc<RefCell<HashMap<i32, i32>>>, } impl Foo { fn iter(&self) -> Values<i32, i32> { self.map.borrow().values() } } fn main() { let foo = Foo { map: Rc::new(RefCell::new(HashMap::new())) }; for v in foo.iter() { println!("{}", v) } } 并且提供访问底层值的接口的守卫,但我需要做的是返回一个已经存在的迭代器对象(rustc 1.15.1 (021bd294c 2017-02-08) error: borrowed value does not live long enough --> <anon>:12:9 | 12 | self.map.borrow().values() | ^^^^^^^^^^^^^^^^^ does not live long enough 13 | } | - temporary value only lives until here | )包含对Ref的简单引用。

我的主要问题是我有一个运行时跟踪引用Values<'a, K, V>,而我需要一个简单的引用来创建一个迭代器。 HashMap公开了一个简单的映射引用,但是它需要mapper函数返回另一个在这里不可能的引用。我应该重做整个迭代器功能以使用Ref<T>还是有更好的方法?

1 个答案:

答案 0 :(得分:3)

你不能这样做。

最终的问题是std::collections::hash_map::Values拥有引用,但您没有“只是”引用。你有智能指针Ref

我所知道的最简单的解决方案是反转代码:

impl Foo {
    fn with_iter<F, T>(&self, f: F) -> T
    where
        F: FnOnce(Values<i32, i32>) -> T,
    {
        f(self.map.borrow().values())
    }
}

fn main() {
    let foo = Foo {
        map: Rc::new(RefCell::new(HashMap::new())),
    };

    foo.with_iter(|i| {
        for v in i {
            println!("{}", v)
        }
    })
}

这里,Values迭代器不再需要比borrow的结果更长,所以没有额外的复杂性。

如果您可以泄露实施,则可以返回Ref

impl Foo {
    fn iter(&self) -> Ref<'_, HashMap<i32, i32>> {
        self.map.borrow()
    }
}
for v in foo.iter().values() {
    println!("{}", v)
}

在较新版本的Rust中,您可以返回实现Deref的未命名类型:

use std::ops::Deref;

impl Foo {
    fn iter(&self) -> impl Deref<Target = HashMap<i32, i32>> + '_ {
        self.map.borrow()
    }
}

另见:

相关问题