如何实现std :: ops :: Index来改变被索引的值?

时间:2017-10-03 12:22:18

标签: rust operator-overloading

我想学习如何将Index特性用于我的玩具roguelike但是甚至无法让它在一个无用的虚拟场景中工作。

use std::ops::Index;

// Dummy struct that wraps i32
#[derive(Clone, Copy, Debug)]
pub struct Integer {
    pub val: i32,
}

impl Integer {
    fn new(num: i32) -> Self {
        Integer { val: num }
    }
}

// Using the index operator on an Integer should add the index to the Integer's value.
// let i = Integer::new(20);
// i[20];
// The above code should make it so i.val == 40
impl Index<Integer> for Integer {
    type Output = i32;

    // The error is in the following line:
    fn index(&self, to_add: Integer) -> &Self::Output {
        self.val + to_add.val;
    }
}

// The code causes an error before it reaches this
fn main() {
    let mut i = Integer::new(20);
    let mut n = Integer::new(30);
    println!("i[20] is: {:?}", i[n]);
}

我收到此错误:

error[E0308]: mismatched types
  --> src/main.rs:23:55
   |
23 |       fn index(&self, to_add: Integer) -> &Self::Output {
   |  _______________________________________________________^
24 | |         self.val + to_add.val;
25 | |     }
   | |_____^ expected &i32, found ()
   |
   = note: expected type `&i32`
              found type `()`

我真的不知道我在说什么,但我想这个价值在它到达函数结尾之前就已经消失了?我还没有完全理解一生。

我知道这看起来像是“没有想到我会做什么修复”的问题,但我很想知道我在这里做错了什么,所以我可以从中学习。

1 个答案:

答案 0 :(得分:1)

  

编者注:在OP彻底改变之前,这个答案适用于原始问题。它不再适用于发布的问题。

Index documentation说,强调我的:

  

Index特征用于指定在不可变上下文中使用的container[index] 等索引操作的功能

您正在尝试 mutate 该值,这根本不可能。您也可以通过index

的签名来说明这一点
pub trait Index<Idx> 
where
    Idx: ?Sized, 
{
    type Output: ?Sized;
    fn index(&self, index: Idx) -> &Self::Output;
}

这里任何地方都没有mut;你不能实现&#34;具有完全不同签名的特征!您也无法更改其中一个参数的类型(在本例中为self)。

直截了当地说,Index是要使用的错误的特征。此外,如果您以这种方式实现代码,那么惯用的Rust用户将真的不高兴;我们通常不会重复使用运营商以获得完全不同的含义。人群。

相反,这应该只是一个名称为

的函数
impl Integer {
    fn increment(&mut self, to_add: i32) {
        self.val += to_add;
    }
}

或者,您可以实施DerefMut

use std::ops::{Deref, DerefMut};

impl Deref for Integer {
type Target = i32;
    fn deref(&self) -> &Self::Target { &self.val }
}

impl DerefMut for Integer {
    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.val }
}

然后像

一样使用它
let mut i = Integer::new(20);
*i += 20;
println!("i[20] is: {:?}", i);