【问题标题】:Destructuring an Option<Box<_>> inside a match statement in Rust在 Rust 的 match 语句中解构 Option<Box<_>>
【发布时间】:2021-06-12 17:25:48
【问题描述】:

我有一个大对象,我需要将它装在另一个对象中,但我不一定总是需要它。所以我想使用 if 语句来获取可选的盒装 TempStructure,但我不确定如何同时解构和取消引用。

例子:

pub struct TempStructure {
    lots_of_data: [u64; 64],
}
pub struct Structure {
    pending_removal: Option<Box<(TempStructure, bool)>>,
}
impl Structure {
    pub fn do_somthing(&mut self) {
        // How do I destructure the Option and dereference the Box to get TempStructure?
        if let Some((temp_structure, some_boolean)) = self.pending_removal.take() { 
            // Do something with temp_structure and some_boolean
        }
    }
}

当我这样做时 ^^^ 我收到 expected struct `std::boxed::Box`, found tuple 错误。

【问题讨论】:

    标签: rust dereference destructuring


    【解决方案1】:

    您可以通过在take() 之后添加.as_deref() 来解决此问题:

    pub struct TempStructure {
        lots_of_data: [u64; 64],
    }
    pub struct Structure {
        pending_removal: Option<Box<(TempStructure, bool)>>,
    }
    impl Structure {
        pub fn do_somthing(&mut self) {
            // How do I destructure the Option and dereference the Box to get TempStructure?
            if let Some((temp_structure, some_boolean)) = self.pending_removal.take().as_deref() { 
                // Do something with temp_structure and some_boolean
            }
        }
    }
    

    Box&lt;T&gt; 取消引用 &amp;Tas_deref() 取消引用 Option 的值,因此它会在您的 Option&lt;Box&lt;T&gt;&gt; 之外为您提供 &amp;T

    编辑:另一种选择是取消对 Box 的引用以将值移出:

            if let Some((temp_structure, some_boolean)) = self.pending_removal.take().map(|boxed| *boxed) { 
                // assignments just for demonstration purposes that we now get
                // owned values rather than references.
                let _: TempStructure = temp_structure;
                let _: bool = some_boolean;
            }
    

    【讨论】:

    • 我想我正在寻找开箱即用的元组,而不仅仅是获取对临时对象的引用。有什么办法可以用.as_deref() 函数做到这一点?
    • 您可以通过取消引用来开箱即用:Rust if let Some((temp_structure, some_boolean)) = self.pending_removal.take().map(|boxed| *boxed) { let _: TempStructure = temp_structure; let _: bool = some_boolean; // Do something with temp_structure and some_boolean }
    • 这将是添加到答案中的一个很好的选择。
    • 我编辑了答案,缺少一些在 SO 上编写 cmets 的经验,任何线索如何修复上面评论中的代码块?
    • 我不认为 cmets 应该有多行代码块。 meta.stackexchange.com/questions/39260/…
    【解决方案2】:

    匹配后取消引用该框:

    if let Some(inner) = self.pending_removal.take() {
        let (temp_structure, some_boolean) = *inner;
        // Do something with temp_structure and some_boolean
    }
    

    (playground)

    如果您认为这有点笨拙,那您是对的。在夜间,您可以使用不稳定的box_patterns 功能为此启用更好的语法(尽管this might never be stabilized):

    if let Some(box (temp_structure, some_boolean)) = self.pending_removal.take() {
        // Do something with temp_structure and some_boolean
    }
    

    (playground)

    【讨论】:

    • 我知道box 语法,但我不知道它被用于此目的。感谢您的展示!
    • @Zyansheep,你不能搬出&amp;mut selfiirc。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-19
    • 2017-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多