将 Vec<Rc<RefCell<T>>> 变成 &[&mut T]
Turning a Vec<Rc<RefCell<T>>> into a &[&mut T]
我有一个引用计数的向量 RefCell
s 并且想将 Vec
的 (mut
) 引用传递给 RefCell
s 到功能。引用不需要超过函数调用。
看起来应该是可以的(只有一个,像&*x.borrow_mut()
这样的就可以了)。我试图保留 RefMut
和 &mut
的中间向量来控制生命周期,但我还没有找到让它工作的方法:
use std::cell::{RefCell,RefMut};
use std::vec::Vec;
use std::rc::Rc;
trait SomeTrait {}
struct Wrapper<'a> {
pub r: &'a mut SomeTrait,
}
fn foo(_: &[Wrapper]) {}
fn main() {
let mut v1: Vec<Rc<RefCell<SomeTrait>>> = unimplemented!();
let mut v_rm: Vec<RefMut<_>> = v1.iter_mut().map(|r| r.borrow_mut()).collect();
let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
foo(&v_wrapper[..]);
}
显然存在终身问题:
rustc 1.11.0 (9b21dcd6a 2016-08-15)
error: borrowed value does not live long enough
--> <anon>:17:60
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^^^^^^^^^^
note: reference must be valid for the block suffix following statement 2 at 17:107...
--> <anon>:17:108
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^
note: ...but borrowed value is only valid for the block at 17:71
--> <anon>:17:72
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
我控制 foo
所以可以改变它的 API 让事情变得更容易,但它在不同的 module/crate 我真的不希望它需要知道我将 SomeTrait
对象保存在 Rc<RefCell<_>>
.
中
虽然可以编写以 Vec<RefMut<T>>
开头并从中创建 Vec<&mut T>
(generic example) 的代码,但我建议您更改 foo
。许多算法不需要切片提供的随机访问,如果函数可以接受迭代器而不是切片,则不需要创建 two 整个额外的 Vec
s,除了调用函数变得更简单。我在想这样的签名
fn foo<I, R>(widgets: I)
where I: IntoIterator<Item=R>,
R: DerefMut<Target=SomeTrait>
{
for widget in widgets {
// ...
}
}
那么您所需要的就是生成一个产生 RefMut
的迭代器,这很容易用 v1.iter_mut().map(|x| x.borrow_mut())
完成。 Here's一个例子。
首先,我同意@delnan 的观点,如果可以的话,您应该切换到基于迭代器的界面。
这段代码的大部分都很好,在将 foo
和 Wrapper
更改为更加灵活之后,我能够调整其余部分并使其编译:
use std::cell::{RefCell,RefMut};
use std::vec::Vec;
use std::rc::Rc;
trait SomeTrait {}
struct Wrapper<'a, 'b> where 'b: 'a {
pub r: &'a mut (SomeTrait + 'b),
}
fn foo<'a, 'b>(_: &'a mut [Wrapper<'a, 'b>]) where 'b: 'a {}
fn main() {
let mut v1: Vec<Rc<RefCell<SomeTrait>>> = unimplemented!();
let mut v_rm: Vec<RefMut<_>> = v1.iter_mut().map(|r| r.borrow_mut()).collect();
let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|mut rm| Wrapper{ r: &mut **rm }).collect();
foo(&mut v_wrapper[..]);
}
这里要理解的关键是每个 trait 对象类型都有一个固定的隐式生命周期,因为 impl 可能包含引用。没有 SomeTrait
这样的类型,只有 SomeTrait + 'a
或 SomeTrait + 'b
或 SomeTrait + 'static
.
您的代码中的问题是 Rust 推断的两件事之间的不匹配。
你写 Rc<RefCell<SomeTrait>>
的地方,Rust 假定你的意思是 Rc<RefCell<SomeTrait + 'static>>
.
你写 fn foo(_: &[Wrapper]) {}
的地方,应用了不同的规则,Rust 假设你的意思是 fn foo<'a>(_: &'a [Wrapper<'a> + 'a])
.
哦。在这些假设下,这个谜题确实没有解,这就是为什么我不得不放松的原因。
如果您不想要那个 'b
生命周期参数,您可以放弃它,只需在使用它的地方(在类型上)将 'b
更改为 'static
Wrapper::r
)。这不太灵活:您将被限制为具有静态生命周期的 SomeTrait
impls。
我有一个引用计数的向量 RefCell
s 并且想将 Vec
的 (mut
) 引用传递给 RefCell
s 到功能。引用不需要超过函数调用。
看起来应该是可以的(只有一个,像&*x.borrow_mut()
这样的就可以了)。我试图保留 RefMut
和 &mut
的中间向量来控制生命周期,但我还没有找到让它工作的方法:
use std::cell::{RefCell,RefMut};
use std::vec::Vec;
use std::rc::Rc;
trait SomeTrait {}
struct Wrapper<'a> {
pub r: &'a mut SomeTrait,
}
fn foo(_: &[Wrapper]) {}
fn main() {
let mut v1: Vec<Rc<RefCell<SomeTrait>>> = unimplemented!();
let mut v_rm: Vec<RefMut<_>> = v1.iter_mut().map(|r| r.borrow_mut()).collect();
let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
foo(&v_wrapper[..]);
}
显然存在终身问题:
rustc 1.11.0 (9b21dcd6a 2016-08-15)
error: borrowed value does not live long enough
--> <anon>:17:60
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^^^^^^^^^^
note: reference must be valid for the block suffix following statement 2 at 17:107...
--> <anon>:17:108
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^
note: ...but borrowed value is only valid for the block at 17:71
--> <anon>:17:72
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
我控制 foo
所以可以改变它的 API 让事情变得更容易,但它在不同的 module/crate 我真的不希望它需要知道我将 SomeTrait
对象保存在 Rc<RefCell<_>>
.
虽然可以编写以 Vec<RefMut<T>>
开头并从中创建 Vec<&mut T>
(generic example) 的代码,但我建议您更改 foo
。许多算法不需要切片提供的随机访问,如果函数可以接受迭代器而不是切片,则不需要创建 two 整个额外的 Vec
s,除了调用函数变得更简单。我在想这样的签名
fn foo<I, R>(widgets: I)
where I: IntoIterator<Item=R>,
R: DerefMut<Target=SomeTrait>
{
for widget in widgets {
// ...
}
}
那么您所需要的就是生成一个产生 RefMut
的迭代器,这很容易用 v1.iter_mut().map(|x| x.borrow_mut())
完成。 Here's一个例子。
首先,我同意@delnan 的观点,如果可以的话,您应该切换到基于迭代器的界面。
这段代码的大部分都很好,在将 foo
和 Wrapper
更改为更加灵活之后,我能够调整其余部分并使其编译:
use std::cell::{RefCell,RefMut};
use std::vec::Vec;
use std::rc::Rc;
trait SomeTrait {}
struct Wrapper<'a, 'b> where 'b: 'a {
pub r: &'a mut (SomeTrait + 'b),
}
fn foo<'a, 'b>(_: &'a mut [Wrapper<'a, 'b>]) where 'b: 'a {}
fn main() {
let mut v1: Vec<Rc<RefCell<SomeTrait>>> = unimplemented!();
let mut v_rm: Vec<RefMut<_>> = v1.iter_mut().map(|r| r.borrow_mut()).collect();
let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|mut rm| Wrapper{ r: &mut **rm }).collect();
foo(&mut v_wrapper[..]);
}
这里要理解的关键是每个 trait 对象类型都有一个固定的隐式生命周期,因为 impl 可能包含引用。没有 SomeTrait
这样的类型,只有 SomeTrait + 'a
或 SomeTrait + 'b
或 SomeTrait + 'static
.
您的代码中的问题是 Rust 推断的两件事之间的不匹配。
你写
Rc<RefCell<SomeTrait>>
的地方,Rust 假定你的意思是Rc<RefCell<SomeTrait + 'static>>
.你写
fn foo(_: &[Wrapper]) {}
的地方,应用了不同的规则,Rust 假设你的意思是fn foo<'a>(_: &'a [Wrapper<'a> + 'a])
.
哦。在这些假设下,这个谜题确实没有解,这就是为什么我不得不放松的原因。
如果您不想要那个 'b
生命周期参数,您可以放弃它,只需在使用它的地方(在类型上)将 'b
更改为 'static
Wrapper::r
)。这不太灵活:您将被限制为具有静态生命周期的 SomeTrait
impls。