【问题标题】:Why do I get expected type `()` when trying to obtain a reference to a boxed value?为什么在尝试获取对装箱值的引用时会得到预期的类型`()`?
【发布时间】:2018-01-04 12:40:30
【问题描述】:

我有这个结构:

pub struct Node<T> {
    value: T,
    left: Option<Box<Node<T>>>,
    right: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    pub fn getLeft(&self) -> Option<&Self> {
        if self.left.is_some() {
            Some(&(*(self.left.unwrap())))
            // Some(self.left.unwrap()) <= same result
        }
        None
    }
}

fn main() {}

当我收到此错误时,似乎存在类型不匹配:

error[E0308]: mismatched types
  --> src/main.rs:10:13
   |
10 |             Some(&(*(self.left.unwrap())))
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::option::Option`
   |
   = note: expected type `()`
              found type `std::option::Option<&Node<T>>`

我是 Rust 新手,不明白为什么预期的类型是 () 而它应该是 Option&lt;&amp;Self&gt; 以及如何返回对框内节点的引用(我如何才能移出借来的自己)?

【问题讨论】:

    标签: rust borrow-checker


    【解决方案1】:

    这里的问题不在于借用检查器。如果您有一个 if 而没有一个 else,您必须返回单位( ())。您正在尝试从函数返回一个值,这意味着您需要有一个else 分支,或者使用return。也就是说:

    impl<T> Node<T> {
        pub fn getLeft(&self) -> Option<&Self> {
            if self.left.is_some() {
                Some(&(*(self.left.unwrap())))
            } else {
                None
            }
        }
    }
    

    好的,现在借用检查器出了问题。这是因为您正在引用一个临时的(self.left.unwrap() 的结果)。您需要在不移动它的情况下访问Option 的内容。所以让我们这样做:

    impl<T> Node<T> {
        pub fn getLeft(&self) -> Option<&Self> {
            if self.left.is_some() {
                Some(&(*(self.left.as_ref().unwrap())))
            } else {
                None
            }
        }
    }
    

    这更好,但它只是丑陋。有unwrap,加上多余的括号,名称不习惯,最后整个分支本身是不必要的。让我们解决所有这些问题:

    impl<T> Node<T> {
        pub fn get_left(&self) -> Option<&Self> {
            self.left.as_ref().map(|l| &**l)
        }
    }
    

    或者,如果你想要更清晰的东西:

    impl<T> Node<T> {
        pub fn get_left(&self) -> Option<&Self> {
            if let Some(left) = self.left.as_ref() {
                Some(&**left)
            } else {
                None
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      您收到错误是因为 if 块是一个表达式;您需要在其后面加上else,以便函数的输出正确(Option&lt;&amp;Self&gt;)。

      此外,您可以利用if let 来获取Option 的内部值;那么很容易从Box中获取参考:

      impl<T> Node<T> {
          pub fn getLeft(&self) -> Option<&Self> {
              if let Some(ref left) = self.left { // if let
                  Some(&*left) // return a reference to the content of the Box (in an Option)
              } else {
                  None // or return None if self.left is None
              }
          }
      }
      

      使用示例:

      fn main() {
          let test0 = Node {
              value: 0,
              left: None,
              right: None
          };
      
          let test1 = Node {
              value: 0,
              left: Some(Box::new(test0)),
              right: None
          };
      
          println!("{:?}", test1.getLeft()); // Some(Node { value: 0, left: None, right: None })
      }
      

      【讨论】:

        猜你喜欢
        • 2020-05-04
        • 1970-01-01
        • 1970-01-01
        • 2019-09-17
        • 1970-01-01
        • 1970-01-01
        • 2021-12-06
        • 2022-10-23
        • 2021-04-03
        相关资源
        最近更新 更多