如何在包装好的HashMap上实现索引?

时间:2016-12-13 10:29:08

标签: rust

我想在HashMap类型上为包装类型实现Index trait:

use std::collections::HashMap;
use std::option::Option;

#[cfg(test)]
use std::ops::Index;

#[derive(Debug, Clone)]
struct Value {
    val: i32,
}

#[derive(Debug, Clone)]
pub struct HMShadow {
    hashmap: HashMap<String, Value>,
}

impl HMShadow {
    fn new() -> HMShadow {
        HMShadow {
            hashmap: {
                HashMap::<String, Value>::new()
            },
        }
    }

    fn insert<S>(&mut self, key: S, element: Value) -> Option<Value>
        where S: Into<String>
    {
        self.hashmap.insert(key.into(), element)
    }

    fn get(&mut self, key: &str) -> &mut Value {
        self.hashmap.get_mut(key).expect("no entry found for key")
    }
}

fn main()
{
    let mut s: HMShadow = HMShadow::new();
    let v: Value = Value { val : 5 };
    let _ = s.insert("test", v);
    println!("{:?}", s);
    println!("Get: {}", s.get("test").val);
}

#[cfg(test)]
impl<'a> Index<&'a str> for HMShadow {
    type Output = &'a mut Value;

    fn index(&self, key: &'a str) -> &&'a mut Value {
        match self.hashmap.get_mut(key) {
            Some(val) => &mut val,
            _ => panic!("no entry found for key"),
        }
    }
}

#[cfg(test)]
#[test]
fn test_index() {
    let mut s: HMShadow = HMShadow::new();
    let v: Value = Value { val : 5 };
    let _ = s.insert("test", v);
    println!("{:?}", s);
    println!("Index: {}", s["test"].val);
}

执行rustc --test tt.rs编译器说:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> tt.rs:51:28
   |
51 |         match self.hashmap.get_mut(key) {
   |                            ^^^^^^^
   |
help: consider using an explicit lifetime parameter as shown: fn index(&'a self, key: &'a str) -> &&'a mut Value
  --> tt.rs:50:5
   |
50 |     fn index(&self, key: &'a str) -> &&'a mut Value {
   |     ^

但是我不能fn index(&'a self, key: &'a str) -> &&'a mut Value因为索引特征不允许&'a self和编译器错误:

  

错误[E0308]:与特征不兼容的方法

2 个答案:

答案 0 :(得分:5)

由于你的问题很不清楚,我将重新解释如下:

  

我正在尝试为我的结构实现Index,但不知何故它不起作用。

错误

在查看编译器错误后,很明显您的Index实现有多种原因是错误的:

  1. Index特征定义了一个名为index的函数,该函数返回对该值的不可变引用。但是,您尝试返回可变引用。当然,Rust抱怨你实现的方法与特征不兼容。
  2. Output实现的Index关联类型不应包含在引用中。因此,您需要type Output = &'a mut Value;
  3. 而不是type Output = Value;
  4. key的生命周期和index函数中的输出不相关,但您同时使用'a
  5. 您需要将Value类型设为公开,才能在特征实施中使用它。
  6. 代码

    Index的正确而简单的实现是:

    impl<'a> Index<&'a str> for HMShadow {
        type Output = Value;
    
        fn index(&self, key: &'a str) -> &Value {
            &self.hashmap[key]
        }
    }
    

答案 1 :(得分:2)

我猜,我在寻找

#[cfg(test)]
impl<'a> IndexMut<&'a str> for HMShadow {
    fn index_mut<'b>(&'b mut self, key: &'a str) -> &'b mut Value {
        self.hashmap.get_mut(key).expect("no entry found for key")
    }
}