IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Rust Discussion :

HashMap et lifetime


Sujet :

Rust

  1. #1
    Membre habitué Avatar de bringer
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2009
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2009
    Messages : 122
    Points : 137
    Points
    137
    Par défaut HashMap et lifetime
    bonjour à tous,
    Je reviens vers vous avec un "classique" soucis de lifetime avec une hashMap. Je veux créer un gestionnaire de scene pour un jeu, J'utilise une HashMap pour stocker mes scenes enregistrées avec une clé string et une valeur Box<dyn Scene>, où Scene est un Trait. Voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    pub trait Scene {
            fn update(&mut self);
            fn draw(&self);
        }
    pub struct SceneManager {
            scenes : HashMap<String, Box<dyn Scene>>,    
            current_scene : Option<Box<dyn Scene>>,
        }
     impl SceneManager {
            pub fn new() -> Self {
                SceneManager {
                    scenes : HashMap::new(),
                    current_scene : None,
                }
            }
    
            pub fn add(&mut self, name : &str, scene : Box<dyn Scene>) {
                self.scenes.insert(String::from(name), scene);
                match self.scenes.get_mut(name) {
                    Some(scene) => self.current_scene = Some(Box::new(scene)), // ici ERREUR, pas possible de récupérer une ref mutable sur ma scene enregistrée
                    None => ()
                }
            }
        }
    
        pub struct SceneGame {
            name : String,
        }
        impl Scene for SceneGame { ...}
    J'ai besoin de récupérer la &mut scene dans self.current_scene pour pouvoir ensuite appeler les methodes update() et draw() sur la scene en cours et je n'y arrive pas. J'ai tenter de mettre une lifetime sur current_scene, mais les soucis persistent.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    pub struct<'a> {
       ...
       current_scene : Option<&'a Box<dyn Scene>>,
     
    mais le soucis n'est pas réglé.
    }
    Je comprend que get() ou get_mut() de HashMap me renvoie une référence, mais je ne comprends pas comment transmettre cette référence à current_scene.
    Voici ce que me renvoie le compilateur :

    the trait bound `&mut std::boxed::Box<(dyn scene_manager::Scene + 'static)>: scene_manager::Scene` is not satisfied

    the trait `scene_manager::Scene` is not implemented for `&mut std::boxed::Box<(dyn scene_manager::Scene + 'static)>`

    note: required for the cast to the object type `dyn scene_manager::Scene`rustc(E0277)
    main.rs(32, 58): the trait `scene_manager::Scene` is not implemented for `&mut std::boxed::Box<(dyn scene_manager::Scene + 'static)>`
    Je ne suis pas contre un petit coup de main.
    Merci à tous et bonne journée.

    Bringer

  2. #2
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 468
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 468
    Points : 6 100
    Points
    6 100
    Par défaut
    Bonjour,

    Avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    pub struct SceneManager {
        scenes: HashMap<String, Box<dyn Scene>>,    
        current_scene: Option<Box<dyn Scene>>,
    }
    le problème est que scenes et current_scene ne peuvent pas partager leurs scènes : chacun est l'unique possesseur de ses objets de type Box<dyn Scene>.

    Dans le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    pub struct SceneManager<'a> {
        scenes: HashMap<String, Box<dyn Scene>>,    
        current_scene: Option<&'a Box<dyn Scene>>,
    }
    il y a bien une séparation entre d'un côté scenes qui possède des objets de type Box<dyn Scene> et current_scene qui ne contient éventuellement qu'une référence vers un objet de type Box<dyn Scene>. Par contre, le borrow checker de Rust va t'embêter.

    En effet, dans le cas général, pour chaque objet, il ne peut y avoir soit qu'une seule référence muable à la fois, soit un nombre quelconque de références, mais toutes immuables.

    Même dans le cas où scenes et current_scene ne sont pas stockés dans la même structure, si tu stockes dans current_scene une référence immuable vers une scène de scenes alors, tant que current_scene existe, cela bloque toute modification de scenes. Ce contrôle empêche, par exemple, que tu fasses scenes.clear() et donc que current_scene se retrouve avec une référence vers une scène qui n'existe plus.

    Une solution de contournement qui me vient à l'esprit sans changer le type de scenes est de remplacer current_scene par une variable qui contient le nom de la scène :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    pub struct SceneManager {
        scenes: HashMap<String, Box<dyn Scene>>,    
        current_scene_name: Option<String>,
    }
    Voici un code dans lequel j'ai ajouté une fonction get_current_scene :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    use std::collections::HashMap;
     
    pub trait Scene {
        fn update(&mut self);
        fn draw(&self);
    }
     
    pub struct SceneManager {
        scenes: HashMap<String, Box<dyn Scene>>,    
        current_scene_name: Option<String>,
    }
     
    impl SceneManager {
        pub fn new() -> Self {
            SceneManager {
                scenes: HashMap::new(),
                current_scene_name: None,
            }
        }
     
        pub fn add(&mut self, name: &str, scene: Box<dyn Scene>) {
            self.scenes.insert(name.to_owned(), scene);
            self.current_scene_name = Some(name.to_owned());
        }
     
        pub fn get_current_scene(&self) -> Option<&Box<dyn Scene>> {
            self.current_scene_name.as_ref().map(|s| self.scenes.get(s).unwrap())
        }
    }
    Par contre, avec ma solution, il n'y aura pas de contrôle à la compilation comme quoi current_scene_name contient forcément le nom d'une scène qui existe. Le contrôle se fera au runtime via l'appel à unwrap() dans la nouvelle fonction get_current_scene ci-dessus.

    Peut-être qu'un autre lecteur du topic proposera une autre solution.

Discussions similaires

  1. [eclipse] HashMap et methode put
    Par topaze dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 26/01/2005, 16h37
  2. Ranger un tableau de String dans ma HashMap
    Par jeyce dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 26/08/2004, 22h41
  3. [HashMap] Modification d'objet d'une Hashtable
    Par viena dans le forum Collection et Stream
    Réponses: 6
    Dernier message: 29/07/2004, 09h04
  4. Surcharge de l'égalité et HashMap
    Par olivierM dans le forum Collection et Stream
    Réponses: 13
    Dernier message: 10/06/2004, 09h54
  5. [débutant] cherche a copier une HashMap
    Par mathieublanc13 dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 09/05/2004, 14h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo