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 :

Questions sur la cohérence de std::set


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 142
    Par défaut Questions sur la cohérence de std::set
    Bonjour à tous.
    Je poste ce fil car je m'intéresse en ce moment au conteneur std::set.

    Tout d'abord, si j'ai bien compris, ce conteneur est censé contenir des instances constantes, uniques et ordonnées du type paramètre.

    Et donc si j'ai bien compris (voir ligne du dessus) et bien je ne comprends pas pourquoi ce conteneur propose (par exemple) :

    1. Un type iterator et un type const_iterator...
      pourquoi pas seulement le const_iterator ?
    2. Une méthode insert qui retourne un iterator et que cette méthode insert puisse prendre en paramètre un const_iterator pour lui indiquer où insérer un élement donné vu que std::set est censé conserver l'ordre...

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    l'ordre est définit par le Compare donné en argument au constructeur
    Il est exigé que les valeurs ne changent pas vis-à-vis de cet ordre, mais rien n'empeche de changer le reste.

    En gros, pour un set<int>, ce serait une erreur de modifier une valeur.
    Mais si tu as des classes possédant un identifiant, un que tu définis une fonction de tri sur cet identifiant (uniquement), tu peux très bien modifier le reste.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 142
    Par défaut
    Bon bon...
    du coup je ne comprends pas ce que dit cette page ?
    Je cite les extraits qui me turlupinent (onglet C++11) :
    Member type Definition Notes
    key_type The first template parameter (T)
    value_type The first template parameter (T)
    iterator a bidirectional iterator to const value_type * convertible to const_iterator
    const_iterator a bidirectional iterator to const value_type *
    *Note: All iterators in a set point to const elements.
    S'agit il d'une erreur de leur part du coup ?

    Et...
    Ma question est due au fait que je comptais me servir de ce conteneur pour une table de symboles rudimentaire.
    En faisant quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    using SymbolsTable = std::set<std::string> ; 
    using SymbolId = std::set<std::string>::const_iterator;
     
    class Identifier
    {
    SymbolId id;
    public :
    Identifier(std::string&& s, SymbolsTable& stab) : id(stab.emplace(std::move(s)).first) {}
    };
    Est-ce une mauvaise idée ?

  4. #4
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Pour la présence d'un couple iterator/const_iterator qui renvoie au même type d'iterator const, c'est à mon avis une question d'harmonisation des interfaces des conteneurs, ça augmente leur généralité.

    Pour le reste il me semble que tu te compliques un peu la vie mais je ne vois pas les tenants et aboutissants de ton idée.

  5. #5
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    cppreference.com dit une chose intéressante:
    iterator
    BidirectionalIterator (until C++11)
    Constant bidirectional iterator (since C++11)
    Il semble donc que iterator n'a pas toujours été constant.

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Oui, de mémoire, la constance des données a été modifiée au cours du temps, car il y avait trop de soucis avec la version trop permissive.
    Pour le fait que insert retourne un iterator, comme tu la vois dans ton code, ça peut servir.
    Pour le fait qu'il en prenne un en paramètre, c'est pour une histoire d'optimisation : Si tu sais déjà à quel endroit l'objet doit être inséré (par exemple parce que tu as fait une recherche infructueuse de cet objet juste avant), et bien autant lui donner un indice pour qu'il trouve cet endroit plus vite, mais de toute manière, il l'insèrera de manière ordonnée.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 142
    Par défaut
    Bon bon ...
    Apparemment ce qui me pose problème ne choque personne du coup je dois l'expliquer un peu plus et peut-être que j'aurai fait un pas dans mon brouillard après que vous m'ayez traité d'idiot.
    D'après ce que dis leternel :
    Mais si tu as des classes possédant un identifiant, un que tu définis une fonction de tri sur cet identifiant (uniquement), tu peux très bien modifier le reste.
    J'imagine la situation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class Foggy{
    /* Des tas de membres dont : */
    TypeIdentifiant Identifiant;
     
    public :
    TypeIdentifiant getIdentifiant() const;
    };
     
    bool compare(TypeIdentifiant, TypeIdentifiant) {/*compare...*/}
    Et voila comment je 'comprends' ce que leternel dit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    std::set<Foggy, compare> mySetOne; //j'imagine que je fais un raccourci avec compare mais ce n'est pas la question ici
    /* 
       on fait des trucs et des machins avec mySetOne 
       mais de toutes façons les objets de type Foggy contenus dans mySetOne
       ne peuvent pas être modifiés (d'après la citation de cppreference ci-dessous).
    */
    The value of the elements in a set cannot be modified once in the container
    Et là ça contredit la partie en gras de la citation de leternel.

    Je peux éventuellement imaginer qu'un type set::iterator soit défini et soit, en fait un set::const_iterator mais ça me semble prêter à confusion...

    Si quelqu'un écrit un algorithme générique sur un conteneur en utilisant un T::iterator c'est qu'a priori il veut modifier la valeur contenu par le conteneur sinon il utiliserait un T::const_iterator non ?

  8. #8
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    C'est parce que j'en étais resté à la définition C++03, et surtout au fait que set utilise un comparateur pour trier.
    Si la vue de l'objet qu'à ce comparateur ne change pas, le tri reste bon, et dans l'absolu, le reste pourrait changer.
    Par défaut, le comparateur est std::less, c'est à dire operator<.

    A présent, j'ai l'impression que le C++11 défini le set comme mieux contraint à la constance.
    J'en suis d'ailleurs satisfait.

  9. #9
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Si quelqu'un écrit un algorithme générique sur un conteneur en utilisant un T::iterator c'est qu'a priori il veut modifier la valeur contenu par le conteneur sinon il utiliserait un T::const_iterator non ?
    On pourrait imaginer quelque chose comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template <class Container, class Fn>
    void for_each_in( Container& c, Fn& f) {
      typedef Container::iterator It;
      for (It it = c.begin(); it != c.end(); ++it) {
        f(*it);
      }
    }
    Dans ces cas-là ça pourrait être une bonne chose.

  10. #10
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Pas forcément, parce que tu te contraints à l'usage d'un itérateur, ce qui n'est pas forcément possible
    D'accord mais c'est justement le but de la fonction, d'utiliser des classes qui définissent toutes seules les bornes de début et de fin par des itérateurs.
    Pour un tableau, de toute façon, il faut un paramètre supplémentaire std::size_t, ou alors passer par des itérateurs et on revient au for_each du standard

  11. #11
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    Sauf que tu as auto, qui est encore plus efficace.
    voire même, le for(auto const& valeur: pack).

    Je crois que c'est std::apply, ta fonction

  12. #12
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Oui, auto est mieux mais l'interface des itérateurs de std::set existait avant
    et pour std::apply, je date un peu, j'ai jeté un oeil sur google et je tombe sur:

    std::experimental::apply

    template <class F, class Tuple>
    constexpr decltype(auto) apply(F&& f, Tuple&& t);

    Call the function object f with a tuple of arguments.
    et je me dis qu'il faut que je révise ma syntaxe pcq decltype(auto) j'ai aucune idée de ce que ça fait

  13. #13
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    Salut
    Citation Envoyé par stendhal666 Voir le message
    Oui, auto est mieux mais l'interface des itérateurs de std::set existait avant
    et pour std::apply, je date un peu, j'ai jeté un oeil sur google et je tombe sur:



    et je me dis qu'il faut que je révise ma syntaxe pcq decltype(auto) j'ai aucune idée de ce que ça fait
    Ben, c'est pourtant simple : il suffit de savoir ce que font decltype et auto

    Auto permet ce que l'on appelle l'inférence de type. En deux mots : cela permet de demander au compilateur de déduire le type auquel il a affaire du type de valeur renvoyée par une fonction.

    Quant à decltype, cela permet ... (faisons simple) de définir un type résultant d'une expression.

    Enfin, constexpr permet juste au compilateur de savoir qu'il s'agit d'une expression constante qu'il devrait être en mesure d'évaluer (et d'utiliser par la suite) par lui-même

    Du coups,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template <class F, class Tuple>
    constexpr decltype(auto) apply(F&& f, Tuple&& t);
    permet au compilateur de savoir
    1. qu'il est en présence d'une expression constante qu'il (qu'il doit ) pouvoir évaluer par lui-même
    2. que cette expression renverra une valeur dont le type dépend d'une expression donnée
    3. qu'on s'attend à ce qu'il détermine par lui-même le type de la valeur en question
    4. que l'expression de base est apply(F&& f, Tuple && t)
    5. que F et T seront déterminés à la compilation en fonction des paramètres fournis lors de l'appel de la fonction (c'est, pour résumer, le principe même des template et du paradigme générique )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. question sur les listes/set/vector
    Par deubelte dans le forum SL & STL
    Réponses: 11
    Dernier message: 04/01/2007, 20h41
  2. question sur les "set/list"
    Par deubelte dans le forum C++
    Réponses: 12
    Dernier message: 29/12/2006, 01h16
  3. question sur les listes/set/vector
    Par deubelte dans le forum SL & STL
    Réponses: 16
    Dernier message: 28/12/2006, 20h17
  4. Question sur set::set
    Par socrate dans le forum C++
    Réponses: 5
    Dernier message: 07/09/2006, 18h22
  5. question sur using std::
    Par d-a-v-e dans le forum SL & STL
    Réponses: 4
    Dernier message: 06/02/2006, 21h41

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