首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从Result<Vec<Data<&T>>>中提取T?

如何从Result<Vec<Data<&T>>>中提取T?
EN

Stack Overflow用户
提问于 2021-09-19 15:15:05
回答 1查看 241关注 0票数 0

我想把SomeTypeResult<Vec<Data<&SomeType>>>中拿出来,然后通过一个通道传递它,但是我失败了:

代码语言:javascript
运行
复制
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
        }
    }
}

错误有:

代码语言:javascript
运行
复制
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似乎没有正确地对待所有权。虽然在Copy上实现SomeType特性可以消除错误,但我不确定CopyClone是否会降低性能。我正在挣扎,但找不到一个正确的方法来解决它。

以下是重新生成错误的完整代码.

代码语言:javascript
运行
复制
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
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-24 20:19:58

当您只有一个&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>> --不要被嵌套的泛型所延迟,只需将它们读为“包含可选SomeTypeRefCell”)。RefCell有一个borrow_mut()方法,为您提供了对内部内容的可变引用,然后您可以在该方法上调用Option::take(),或者您可以调用RefCell::take(),它将自己做正确的事情。

代码语言:javascript
运行
复制
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();
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69244550

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档