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

SL & STL C++ Discussion :

Itérateur : Abstraction du type de la collection


Sujet :

SL & STL C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 142
    Par défaut Itérateur : Abstraction du type de la collection
    Salut à tous, développeurs noctambules ! (oui, 22h30 c'est tard pour programmer)

    Admettons que j'ai une classe Directory, qui est une collection d'objets de type File.
    Je fais le choix de stocker mes Files dans une liste chainée (ça pourrait être plus judicieux, mais là n'est pas la question).
    Une classe client va donc parcourir la collection avec un code qui ressemble à ceci (je vous apprends rien) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Directory dir;
    list<File*> files = dir.GetFiles();
    for(list<File*>::iterator it = files.begin(); it != files.end(); it++)
    {
      //bla bla bla
    }
    Ça marche très bien, là n'est pas le problème. Mais de toute évidence, ce code montre que l'implémentation de Directory est insuffisamment encapsulée (on voit quel type de collection est utilisé). Et comme chacun sait, ne pas encapsuler correctement, c'est mal.


    Je m'attèle donc à utiliser un type d'itérateur générique. Je m'aperçois qu'il existe un header <iterator> dans la STL et décide donc d'explorer tout cela pour voir quel type serait le plus adapté.
    Attention, à partir de ce point, ça devient hautement expérimental.
    Je tente de modifier la méthode GetFiles().
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    iterator<bidirectional_iterator_tag, File*> Directory::GetFiles()
    {
      //je sais pas encore quoi
    }
    De cette façon, l'implémentation est bien encapsulée.
    Sauf que je ne sais pas comment aller au bout de cette idée.


    Comment faire pour encapsuler le type de la collection ?

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    92
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2005
    Messages : 92
    Par défaut
    Tu dois pouvoir aussi affecter une interface de conteneur à la classe Directory:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Directory
    {
    public:    
        typedef std::list<file>::iterator iterator;
        iterator begin() { return m_files.begin(); }
        iterator end() { return m_files.end(); }
        // idem versions const ?
     
        ...
     
    private:
        std::list<file> m_files;
    };
    Puis l'utiliser comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Directory dir;
    for (Directory::iterator i = dir.begin(); i != dir.end(); ++i)
    {
        ...
    }
    Mais bon, c'est pas tout-à-fait la même fonctionnalité.

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

    Informations forums :
    Inscription : Février 2007
    Messages : 142
    Par défaut
    J'avais déjà testé une solution à base de typedef, mais étrangement je me rappelle pas avoir obtenu une syntaxe aussi limpide que celle que tu me présentes là… ce qui est un bon point
    Bon, par contre, avec cette solution, comment je fais si je veux utiliser un const_iterator ? Ou un reverse_iterator, ou tous les autres ?

    Ils doivent bien servir à quelque chose ces foutus types iterator et iterator_*_tag !

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    92
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Côte d'Or (Bourgogne)

    Informations forums :
    Inscription : Mai 2005
    Messages : 92
    Par défaut
    Bon, par contre, avec cette solution, comment je fais si je veux utiliser un const_iterator ? Ou un reverse_iterator, ou tous les autres ?
    Et bien tu te fais couler un café et tu rajoutes autant de typedefs et de méthodes que nécessaire pour que l'interface de conteneur soit la plus complète possible ! Sans oublier les value_type, reference, const_reference, size_type, difference_type, etc. Et même les size(), empty(), operators et autres .

    Bon, c'est vrai que les iterator_traits/tags, j'ai jamais essayé ... Je me disais que c'était plutôt fait pour implémenter des itérateurs ayant des fonctionnalités propres en plus de celles des conteneurs STL fournis avec le standard.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 142
    Par défaut
    Je n'ai aucune connaissance dans les concepts de traits et de tags (?) en C++. Je ferais mieux de me renseigner à ce propos.

    Ceci dit, ce problème serait une bonne application de ces notions, et j'encourage les experts en la matière à me donner un coup de main

    Merci à toi, Biozic !

  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
    Les iterator_ags sont là pour pallier une déficience du C++ actuel (les concepts en c++0x devraient simplifier et clarifier ça). Imaginons un algorithme templatisé par un itérateur, qui puisse s'implémenter de deux façon, selon que l'itérateur est à accès aléatoire ou seulement un forward iterator. Il faudrait pouvoir surcharger cet algorithme en fonction de la catégorie d'itérateur à laquelle appartient l'itérateur.

    Or, il est uniquement possible de surcharger en fonction d'un type. L'astuce consiste donc à ce que la personne qui défini un itérateur lui associe un type, conventionnel, qui puisse permettre à l'algorithme de s'y retrouver. Ce sont les
    iterator_tags, un iterator_trait permettant de regrouper cette info et d'autres du même genre.

    Et comme c'est lourd à définir ça, il y a une méthode pour associer tous les types liés à une catégorie en faisant dériver un itérateur perso d'une classe de base.

    Donc, en gros, si on défini son itérateur perso, sans le faire dériver de la classe de base qui va bien, si définir la classe de traits associée, il y a de bonne chances pour qu'on ne puisse pas l'utiliser avec les algorithmes. Réciproquement, si on veut implémenter un algorithme efficacement, utiliser les iterator_tags peut y aider.

    Pour ta question initiale, j'attends aussi une autre fonctionnalité du C++0x, qui permettra d'écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Directory dir;
    auto files = dir.GetFiles();
    for(auto it = files.begin(); it != files.end(); it++)
    {
      //bla bla bla
    }
    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.

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

Discussions similaires

  1. Unknown abstract schema type
    Par ekremyilmaz dans le forum JPA
    Réponses: 6
    Dernier message: 10/03/2009, 21h01
  2. créer un objet à partir du type d'une collection
    Par dams78 dans le forum Collection et Stream
    Réponses: 11
    Dernier message: 03/11/2008, 14h08
  3. Réponses: 1
    Dernier message: 07/10/2008, 15h49
  4. type variable item collection
    Par samtheh dans le forum VBA Access
    Réponses: 10
    Dernier message: 31/05/2007, 13h31

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