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

C++ Discussion :

Map, Set et range-based for


Sujet :

C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut Map, Set et range-based for
    Bonjour à tous,

    A ma grande stupéfaction, je n'arrive pas à utiliser le range-based for avec une std::map qui a pour clé un std::string et pour valeur un std::set<Foo>.

    Foo est construit de la manière suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    struct Foo
    {
        Foo() : id(ID++), x(42) {}
        Foo(const Foo&) = default;
        Foo(Foo&&) = default;
     
        int id;
        int x;
    };
     
    bool operator<(const Foo& f1, const Foo& f2) 
    {
        return f1.id < f2.id;
    }
    Mon but est de mettre à jour x au sein de la map.

    Je n'ai pas trouver d'autres moyen que de faire le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void modifyMap(std::map<std::string, std::set<Foo>>& mFoo)
    {
        for (auto& kv : mFoo) {
            auto tmp = kv.second;
            kv.second.clear();
            for (auto foo : tmp) {
                auto tmpFoo = foo;
                tmpFoo.x = 5;
                kv.second.insert(tmpFoo);
            }
        }    
    }
    Le problème de ce code est que je fais de nombreuses copies. Serait-il possible de simplement modifier le contenu de mes objets (Sans changer de conteneur)?

    Merci

    Edit: J'ai réussi en utilisant des pointeurs (std::shared_ptr pour être plus précis) mais du coup on perd la notion de droit d'écriture. Si certains ont d'autres idées en utilisant directement les objets, je suis preneur. Je mettrais résolu d'ici 2-3 jours sinon.

  2. #2
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Un map de set ne me semble pas très efficace, mais passons.

    Les conteurs associatifs possèdent des clefs qui ne peuvent pas être modifiées. Comme les éléments d'un std::set sont aussi bien des valeurs que des clefs, on ne peut pas les modifier. Boost possède un conteneur type std::set où les clefs peuvent être modifiées, mais qui demande un update manuel.

    En c++17, il y a la fonction membre extract qui retour un node_type avec une clef non-const qui peut ensuite être injecté avec insert. Mais cela est peu adapté pour modifier toutes les valeurs du conteneur (c'est plus pensé pour déplacer un noeud d'un conteneur à un autre).

    Sans changer la structure du code, il y a 2 manières de faire qui ressemblent plus à des hacks:
    - const_cast pour modifier x qui ne fait pas partit du prédicat de tri.
    - mettre x en mutable.

    Sinon, il faut séparer id et x dans un conteneur associatif std::map<int,int>. Ce qui reviendrait à manipuler un std::map<std::pair<std::string, int>, int>, mais de manière moins efficace.

  3. #3
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Un set ne permet pas la modification de ses éléments.
    La raison en est qu'il y a une intégrité entre les éléments (la règle d'unicité), et qu'une modification pourrait détruire cette intégrité.

    Tu n'as pas d'autre solution que d'enlever et remettre dans le set.

    Ta seule alternative est de remplacer le set par une map de la "partie clé" vers la "partie donnée"
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  4. #4
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Merci pour vos conseils.
    Je voulais éviter justement tous ces hacks ou faire une map de map. Mais bon, s'il n'y a pas encore de possibilité (nous n'utilisons pas encore C++17), je vais me contenter d'enlever et remettre dans le set (il y a peu d'objet donc ça n'est pas très gênant).

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Je sais pas trop ce que c'est Foo, mais si c'est pour tous les mettre à 5, et puisque tu comptes les modifier à priori, t'es sûr qu'un vector c'est pas mieux ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Personnellement, c'est le moment où je créerai une classe dédiée, qui ferait le travail proprement.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Traduction de "range based" for loop
    Par ram-0000 dans le forum Langage
    Réponses: 6
    Dernier message: 01/03/2013, 11h15
  2. Réponses: 6
    Dernier message: 15/11/2012, 11h53
  3. Réponses: 7
    Dernier message: 07/12/2009, 22h49
  4. connaitre le character set d'une base
    Par slausseur dans le forum Administration
    Réponses: 4
    Dernier message: 17/09/2007, 11h30
  5. Changer le character set d'une base
    Par Rakken dans le forum Oracle
    Réponses: 2
    Dernier message: 21/11/2006, 17h21

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