2017-10-03 11 views
0

Je veux apprendre à utiliser le trait Index pour mon jouet roguelike mais je ne peux même pas le faire fonctionner dans un scénario fictif inutile.Comment implémenter std :: ops :: Index pour faire muter la valeur en cours d'indexation?

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]); 
} 

Je reçois cette erreur:

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 `()` 

Je ne sais pas vraiment ce que je parle, mais je suppose que la valeur meurt avant d'atteindre la fin de la fonction ou quelque chose comme ça ? Je ne comprends pas encore complètement les vies. Je sais que cela ressemble à une question "AUCUNE IDÉE QU'IL FAUT FAIRE FIXER", mais j'aimerais savoir ce que je fais de mal ici afin que je puisse apprendre de lui.

+1

Signature 'index' est' index (& self, Idx) -> & Self :: Output', pas 'index (mut self, ...) ...' ' – red75prime

Répondre

1

Editor's note: This answer applied to the original question before the OP completely changed it. It is no longer applicable to the posted question.


Le Index documentation dit, Souligné par l'auteur:

The Index trait is used to specify the functionality of indexing operations like container[index]when used in an immutable context.

Vous essayez de muter la valeur, ce qui est tout simplement impossible. Vous pouvez également dire ceci à partir de la signature de index:

pub trait Index<Idx> 
where 
    Idx: ?Sized, 
{ 
    type Output: ?Sized; 
    fn index(&self, index: Idx) -> &Self::Output; 
} 

Il n'y a pas mut partout ici; vous ne pouvez pas "implémenter" un trait avec une signature complètement différente! Vous ne pouvez pas non plus modifier le type de l'un des arguments (dans ce cas, self).


Carrément mis, Index est le trait mauvais à utiliser. De plus, les utilisateurs idiomatiques de Rust seraient vraiment bouleversé si vous avez implémenté le code de cette façon; nous ne sommes généralement pas de la catégorie «réutiliser un opérateur pour une signification complètement différente».

Au lieu de cela, cela devrait juste être une fonction avec un nom:

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

Sinon, vous pouvez mettre en œuvre 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 } 
} 

Et puis utiliser comme

let mut i = Integer::new(20); 
*i += 20; 
println!("i[20] is: {:?}", i); 
+0

Je me suis rendu compte que et je l'ai changé pour juste ajouter au lieu de mutation, je vais éditer la question – omrisim210

+0

@ omrisim210 donc, vous souhaitez invalider la réponse? C'est très mal vu. – Shepmaster

+0

@ omrisim210 par exemple - https://meta.stackoverflow.com/q/266946/155423 – Shepmaster