2016-11-26 35 views
0

考虑下面的代码(这并没有做太多尚未):类型不匹配的返回结构(预计<K, V>,发现<&K, &V>)

use std::collections::BTreeMap; 
use std::iter::FromIterator; 

trait Node<K, V> { 
    fn split(&self) -> Split<K, V>; 
} 

#[derive(Debug, Copy, Clone)] 
pub struct Config { 
    data_b: usize, 
} 

struct Split<'a, K, V> { 
    left: Box<Node<K, V> + 'a>, 
    right: Box<Node<K, V> + 'a>, 
} 

#[derive(Debug)] 
pub struct DataNode<K, V> { 
    cfg: Config, 
    children: BTreeMap<K, V>, 
} 

impl<K: Clone + Ord, V: Clone> Node<K, V> for DataNode<K, V> { 
    fn split(&self) -> Split<K, V> { 
     let data_b = self.cfg.data_b; 

     Split { 
      left: Box::new(DataNode { 
       cfg: self.cfg.clone(), 
       children: BTreeMap::from_iter(self.children.iter().take(data_b)) 
      }), 
      right: Box::new(DataNode { 
       cfg: self.cfg.clone(), 
       children: BTreeMap::from_iter(self.children.iter().rev().take(data_b)) 
      }), 
     } 
    } 
} 

编译器提供了以下错误:

error[E0308]: mismatched types 
    --> lib.rs:68:9 
    | 
68 |   Split { 
    |  ^expected type parameter, found &K 
    | 
    = note: expected type `Split<'_, K, V>` 
    = note: found type `Split<'_, &K, &V>` 

我对Rust很新,所以我不确定是什么原因造成的。要说得很清楚,我遇到的问题是而不是关于什么错误消息意味着。显然,这意味着我没有返回正确的类型。问题是为什么是否编译器将此Split {...}代码解释为当我期望它为Split<'_, K, V>时返回Split<'_, &K, &V>的代码。任何见解都会被赞赏。

+0

你明白[*什么引用*](https://doc.rust-lang.org/stable/book/references-和borrowing.html)?你知道['BTreeMap :: iter'](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.iter)是如何工作的吗?国际海事组织,错误信息是非常简单的 - 你说过你会回报一件事,但你回来了别的东西。我们可以进一步澄清哪些信息缺失? – Shepmaster

+0

我没有说我不明白错误信息。我不明白的是为什么我在'Split <'_, &K, &V>'中写过结果。如果它与使用迭代器的细微之处有关,那么,这超出了我的Rust知识水平,我希望有一些洞察力。在来这里之前,我能做的最好的事情是检查返回什么类型的东西,但什么都没有表明引用会起作用。所以不知何故,编译器觉得不得不做出这样的要求,我想了解为什么以及如何才能得到我想要的,如果可能的话。 – neverfox

回答

2

的引用来自哪里你迭代的孩子建立一个新的BTreeMap

BTreeMap::from_iter(self.children.iter().take(data_b)) 

如果你看一下iterator returned by BTreeMap::iter(),该Item类型:

type Item = (&'a K, &'a V) 

即迭代器返回对内容的引用。这很有意义,因为您不想在迭代时将项目移出地图,或者依赖于Copy

这与例如Vec::iter(),是一对参考文献,而不是一对参考文献。这是有道理的,因为对pair的引用意味着容器必须在内部实际包含这些对(限制内部数据结构)。

最简单的事情是克隆键和值:

BTreeMap::from_iter(self.children.iter() 
           .map(|(&a, &b)| (a.clone(), b.clone())) 
           .take(data_b)) 
+0

感谢您的明确解释并指出可能的解决方案。你说得对,它确实有道理。我在所有使用的各种方法中检查了类型,但我被文档误导,说'fn iter(&self) - > Iter '所以我正在抓我的头。现在我知道我应该在哪里寻找。 – neverfox

+1

我在网上文档中做了很多点击类型!你学习各种各样的东西。 –

相关问题