如何从Result<Vec<Data<&T>>>中取出T?
How to take T out of Result<Vec<Data<&T>>>?
我想从Result<Vec<Data<&SomeType>>>
中取出SomeType
,然后通过通道传递,但是我失败了:
pub fn read(result: Result<Vec<Data<&SomeType>>, ()>, tx: mpsc::Sender<SomeType>) {
if let Ok(datas) = result {
for data in datas.iter() {
let actual_data = data.value();
let some_type_instance = SomeType { k: 1 };
tx.send(some_type_instance); // works
tx.send(**actual_data); // errors
}
}
}
错误:
error[E0507]: cannot move out of `**actual_data` which is behind a shared reference
--> src/main.rs:40:21
|
40 | tx.send(**actual_data);
| ^^^^^^^^^^^^^ move occurs because `**actual_data` has type `SomeType`, which does not implement the `Copy` trait
似乎 tx
没有正确取得所有权。虽然在 SomeType
上实现 Copy
特性可以消除错误,但我不确定 Copy
或 Clone
是否会降低性能。我正在努力解决它,但找不到正确的方法来修复它。
以下是重现错误的完整代码
use std::result::Result;
use std::sync::mpsc;
pub struct SomeType {
k: i32,
}
pub struct Data<D> {
value: D,
}
impl<D> Data<D> {
pub fn value(&self) -> &D {
&self.value
}
}
pub fn main() {
let a = SomeType { k: 1 };
let b = SomeType { k: 2 };
let c = SomeType { k: 3 };
let A = Data { value: &a };
let B = Data { value: &b };
let C = Data { value: &c };
let datas = vec![A, B, C];
let result = Ok(datas);
let (tx, rx) = mpsc::channel();
read(result, tx);
}
pub fn read(result: Result<Vec<Data<&SomeType>>, ()>, tx: mpsc::Sender<SomeType>) {
if let Ok(datas) = result {
for data in datas.iter() {
let actual_data = data.value();
let some_type_instance = SomeType { k: 1 };
tx.send(some_type_instance); // this line works
tx.send(**actual_data); // this line errors
}
}
}
当你只有一个 &T
时,如果不克隆引用后面的值,你将无法获得 T
,因为提取非复制值会 移动 它,并且提供参考的 T
(此处 Data
)的所有者希望该值保持有效。
但是,如果您控制存储在 Data
中的类型,则可以将您的实际值包装在 Option
中。然后,您可以使用 std::mem::replace(ref_to_t, None)
获取引用后面的值,并将 None
留在原处。 Option
甚至有一个 take()
方法可以为您做到这一点。
但是 mem::replace()
和 Option::take()
都需要一个可变引用,而你所拥有的只是一个共享引用。要解决这个问题,您还需要使用内部可变性,例如 RefCell
提供的。然后你将放入 Data
的类型是 RefCell<Option<SomeType>>
- 不要被嵌套的泛型推迟,只需将它们读作“RefCell
包含一个可选的 SomeType
” . RefCell
有一个 borrow_mut()
方法,为您提供对内部内容的可变引用,然后您可以在该方法上调用 Option::take()
,或者您可以调用 RefCell::take()
,这将做正确的事情自己。
pub fn main() {
let a = SomeType { k: 1 };
let b = SomeType { k: 2 };
let c = SomeType { k: 3 };
let da = Data {
value: RefCell::new(Some(a)),
};
let db = Data {
value: RefCell::new(Some(b)),
};
let dc = Data {
value: RefCell::new(Some(c)),
};
let datas = vec![da, db, dc];
let (tx, _rx) = mpsc::channel();
read(&datas, tx);
}
pub fn read(datas: &[Data<RefCell<Option<SomeType>>>], tx: mpsc::Sender<SomeType>) {
for data in datas {
let actual_data = data.value().take().unwrap();
tx.send(actual_data).unwrap();
}
}
我想从Result<Vec<Data<&SomeType>>>
中取出SomeType
,然后通过通道传递,但是我失败了:
pub fn read(result: Result<Vec<Data<&SomeType>>, ()>, tx: mpsc::Sender<SomeType>) {
if let Ok(datas) = result {
for data in datas.iter() {
let actual_data = data.value();
let some_type_instance = SomeType { k: 1 };
tx.send(some_type_instance); // works
tx.send(**actual_data); // errors
}
}
}
错误:
error[E0507]: cannot move out of `**actual_data` which is behind a shared reference
--> src/main.rs:40:21
|
40 | tx.send(**actual_data);
| ^^^^^^^^^^^^^ move occurs because `**actual_data` has type `SomeType`, which does not implement the `Copy` trait
似乎 tx
没有正确取得所有权。虽然在 SomeType
上实现 Copy
特性可以消除错误,但我不确定 Copy
或 Clone
是否会降低性能。我正在努力解决它,但找不到正确的方法来修复它。
以下是重现错误的完整代码
use std::result::Result;
use std::sync::mpsc;
pub struct SomeType {
k: i32,
}
pub struct Data<D> {
value: D,
}
impl<D> Data<D> {
pub fn value(&self) -> &D {
&self.value
}
}
pub fn main() {
let a = SomeType { k: 1 };
let b = SomeType { k: 2 };
let c = SomeType { k: 3 };
let A = Data { value: &a };
let B = Data { value: &b };
let C = Data { value: &c };
let datas = vec![A, B, C];
let result = Ok(datas);
let (tx, rx) = mpsc::channel();
read(result, tx);
}
pub fn read(result: Result<Vec<Data<&SomeType>>, ()>, tx: mpsc::Sender<SomeType>) {
if let Ok(datas) = result {
for data in datas.iter() {
let actual_data = data.value();
let some_type_instance = SomeType { k: 1 };
tx.send(some_type_instance); // this line works
tx.send(**actual_data); // this line errors
}
}
}
当你只有一个 &T
时,如果不克隆引用后面的值,你将无法获得 T
,因为提取非复制值会 移动 它,并且提供参考的 T
(此处 Data
)的所有者希望该值保持有效。
但是,如果您控制存储在 Data
中的类型,则可以将您的实际值包装在 Option
中。然后,您可以使用 std::mem::replace(ref_to_t, None)
获取引用后面的值,并将 None
留在原处。 Option
甚至有一个 take()
方法可以为您做到这一点。
但是 mem::replace()
和 Option::take()
都需要一个可变引用,而你所拥有的只是一个共享引用。要解决这个问题,您还需要使用内部可变性,例如 RefCell
提供的。然后你将放入 Data
的类型是 RefCell<Option<SomeType>>
- 不要被嵌套的泛型推迟,只需将它们读作“RefCell
包含一个可选的 SomeType
” . RefCell
有一个 borrow_mut()
方法,为您提供对内部内容的可变引用,然后您可以在该方法上调用 Option::take()
,或者您可以调用 RefCell::take()
,这将做正确的事情自己。
pub fn main() {
let a = SomeType { k: 1 };
let b = SomeType { k: 2 };
let c = SomeType { k: 3 };
let da = Data {
value: RefCell::new(Some(a)),
};
let db = Data {
value: RefCell::new(Some(b)),
};
let dc = Data {
value: RefCell::new(Some(c)),
};
let datas = vec![da, db, dc];
let (tx, _rx) = mpsc::channel();
read(&datas, tx);
}
pub fn read(datas: &[Data<RefCell<Option<SomeType>>>], tx: mpsc::Sender<SomeType>) {
for data in datas {
let actual_data = data.value().take().unwrap();
tx.send(actual_data).unwrap();
}
}