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

Har*_*yer 1 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);
}
Run Code Online (Sandbox Code Playgroud)

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 {
   |     ^
Run Code Online (Sandbox Code Playgroud)

但我不能这样做fn index(&'a self, key: &'a str) -> &&'a mut Value因为Index trait不允许&'a self和编译错误:

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

aoc*_*via 5

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

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

错误

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

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

代码

一个正确而简单的实现Index将是:

impl<'a> Index<&'a str> for HMShadow {
    type Output = Value;

    fn index(&self, key: &'a str) -> &Value {
        &self.hashmap[key]
    }
}
Run Code Online (Sandbox Code Playgroud)