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 :

Template container en C++


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    �tudiant
    Inscrit en
    Juin 2014
    Messages
    6
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 30
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activit� : �tudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 6
    Par d�faut Template container en C++
    Bonjour,

    Je d�bute en C++. Je veux faire une classe PersistenceDiagram qui :

    1) contient un ensemble de points (de type Diagram_point, cf typedef) dans un container de la stl
    2) dispose d'un certain nombre de m�thodes, disons une m�thode pour ajouter des points + un iterator

    Seulement je veux qu'on puisse choisir quel container de la stl on utilise (list, vector, etc..) pour stocker les points dans le PersistenceDiagram � chaque fois qu'on en cr�e un. Donc PersistenceDiagram doit �tre un template, le param�tre de ce template est un container de la stl, c'est � dire un autre template. J'ai �crit �a :

    Header :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #pragma once
    #include <utility>
    #include <list>
    typedef typename std::pair<double,double> Diagram_point;
    template < template< class > Container > class PersistenceDiagram{
    private:
        Container< Diagram_point > points;
    public:
        template < template<class> Container > PersistenceDiagram();
        void add_point(Diagram_point p);
        template < template<class> Container > typename Container< Diagram_point >::iterator begin();
        template < template<class> Container > typename Container< Diagram_point >::iterator end();
    };
    .cpp :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #include "persistenceDiagram.hpp"
    template < template<class> Container > PersistenceDiagram::PersistenceDiagram(){
        points = Container< Diagram_point >();
    }
    void PersistenceDiagram::add_point(Diagram_point p){
        points.push_back(p);
    }
    template < template<class> Container > typename Container< Diagram_point >::iterator PersistenceDiagram::begin(){
        return points.cbegin();
    }
    template < template<class> Container > typename Container< Diagram_point >::iterator PersistenceDiagram::end(){
        return points.cend();
    }
    Exemple d'utilisation qui doit �tre possible :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
     
    PersistenceDiagram<std::list> my_persistence_diagram();
    PersistenceDiagram<std::vector> my_persistence_diagram2();
    my_persistence_diagram.add_point(my_point); // my_point est de type Diagram_point
    Pour l'instant g++ me balance plusieurs pages d'erreurs, je pense qu'il est sage de se limiter � la premi�re pour commencer :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
     
    In file included from main.cpp:15:0:
    persistenceDiagram.hpp:10:28: error: expected 'class' before 'Container'
    template < template< class > Container > class PersistenceDiagram{
                                ^
    Je ne vois vraiment pas pourquoi il me dit �a, j'ai d�j� indiqu� le type du param�tre du template : il s'agit d'un autre template, ce dernier prend en param�tre une classe. Ca n'a pas de sens de me demander de mettre un deuxi�me type pour Container...

    Merci d'avance,
    Je me tiens � votre disposition pour toute pr�cision/reformulation/explication n�cessaire.

  2. #2
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    F�vrier 2009
    Messages
    762
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2009
    Messages : 762
    Par d�faut
    Salut,

    Comme le compilateur te le dis :

    expected 'class' before 'Container'
    Donc tu mets 'class' avant 'Container' ce qui donne :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    template <template<class> class Container> ...
    Bon t'auras encore d'autres probl�me vu que vector prend 2 arguments template (comme l'allocator), et puis apr�s les std::set te poseront probl�mes vu qu'il y a 3 arguments template. En gros si j'�tais toi je me passerais des arguments template template, c'est pas terrible et pas souvent utilis� (j'ai des solutions plus �l�gantes si tu tiens vraiment � utiliser cette technique). � choisir tu peux faire quelque chose comme :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    PersistantDiagram<std::vector<DiagramPoint>> diag;
    ...
    Aussi est-ce que ton persistant diagram aura des responsabilit�s suppl�mentaires par rapport � un container classique, en quoi il diff�re d'un simple container ?

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    �tudiant
    Inscrit en
    Juin 2014
    Messages
    6
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 30
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activit� : �tudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 6
    Par d�faut
    Avant tout, merci pour ta r�ponse.

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
     
    template <template<class> class Container> ...
    D'accord mais je ne comprends pas ce que vient faire le mot class ici, le type de Container est template<class>, non ?

    Bon t'auras encore d'autres probl�me vu que vector prend 2 arguments template (comme l'allocator), et puis apr�s les std::set te poseront probl�mes vu qu'il y a 3 arguments template. En gros si j'�tais toi je me passerais des arguments template template, c'est pas terrible et pas souvent utilis� (j'ai des solutions plus �l�gantes si tu tiens vraiment � utiliser cette technique).

    Aussi est-ce que ton persistant diagram aura des responsabilit�s suppl�mentaires par rapport � un container classique, en quoi il diff�re d'un simple container ?
    Bonnes questions qui vont m'aider � avancer, merci. Faut que j'y r�fl�chisse, je uperai/editerai demain.

  4. #4
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    F�vrier 2009
    Messages
    762
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2009
    Messages : 762
    Par d�faut
    Citation Envoy� par NoVGAcable Voir le message
    D'accord mais je ne comprends pas ce que vient faire le mot class ici, le type de Container est template<class>, non ?
    Vu qu'un container est d�clar� de cette mani�re :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    template <class T, class Alloc>
    class vector;
    et pas de cette mani�re :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    template <class T, class Alloc>
    vector;
    Il est plus logique de d�clarer ton template comme tu d�clares la classe, � mon avis c'est la raison sous-jacente, apr�s pour ce qui est de la syntaxe du bouzin, je suis d'accord que �a fait un peu "bricol�", mais g�n�ralement le C++ est un peu un langage comme �a vu qu'il est plut�t mis-�-jour avec un processus d'ing�nierie plut�t que de recherche.

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    D�tails du profil
    Informations personnelles :
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par d�faut
    Citation Envoy� par Trademark Voir le message
    j'ai des solutions plus �l�gantes si tu tiens vraiment � utiliser cette technique
    Je suis tr�s int�ress� par �a, si tu pouvais d�velopper J'ai un code que je n'ai pas r�ussi � �crire sans argument template template, alors tout conseil pour proprifier est bon � prendre pour moi.

  6. #6
    Membre �prouv�
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par d�faut
    Citation Envoy� par NoVGAcable Voir le message
    D'accord mais je ne comprends pas ce que vient faire le mot class ici, le type de Container est template<class>, non ?
    Il y a une explication dans le chapitre 5.4 de C++ Templates - The Complete Guide.

  7. #7
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    F�vrier 2009
    Messages
    762
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2009
    Messages : 762
    Par d�faut
    Citation Envoy� par jblecanard Voir le message
    Je suis tr�s int�ress� par �a, si tu pouvais d�velopper J'ai un code que je n'ai pas r�ussi � �crire sans argument template template, alors tout conseil pour proprifier est bon � prendre pour moi.
    Dans l'exemple de l'OP, j'aurais simplement utiliser du "rebinding de type" pour faciliter l'utilisateur, ce qui donnerait :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    namespace simple{
     
    template <class T>
    using vector = std::vector<T>;
     
    template <class T>
    using set = std::set<T>;
     
    }
     
    PersistantDiagram<simple::vector> diag;
    �a permet d'uniformiser l'interface template des arguments. Par contre �a utilise encore les template-template. Une solution n'utilisant pas les templates-templates serait :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
     
    struct arg1;
     
    PersistantDiagram<std::vector<arg1>> diag;
    Avec la classe PersistantDiagram utilisant un m�canisme pour "rebind" le type comme :

    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
     
    template <class NewType, class T> struct rebind_type;
     
    template <class NewType, class T, class Alloc>
    struct rebind_type<NewType, std::vector<T, Alloc>>
    {
      using type = std::vector<NewType, Alloc>;
    };
     
    template <class NewType, class T, class Alloc, class Compare>
    struct rebind_type<NewType, std::set<T, Alloc, Compare>>
    {
      using type = std::set<NewType, Alloc, Compare>;
    };
     
    template <class NewType, class T>
    using rebind_type_t = rebind_type<NewType, T>::type;
     
    // Et on utilise ça comme ça :
    template <class Container>
    class PersistantDiagram
    {
      using container_type = rebind_type_t<Diagram, Container>;
    };
    C'est donc similaire � std::bind mais pour les templates, � mon avis mpl::bind est le syst�me g�n�ralis� mais j'ai pas cherch� � l'appliquer � l'exemple pour voir si c'�tait exactement �a.

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    �tudiant
    Inscrit en
    Juin 2014
    Messages
    6
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 30
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activit� : �tudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 6
    Par d�faut
    Merci pour ces r�ponses, j'ai compris pas mal de choses, je me suis inspir� de vos propositions ainsi que du chapitre 5.4 de C++ Templates - The Complete Guide pour faire ceci :

    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
    31
    32
    33
     
    #pragma once
    #include <utility>
     
    typedef typename std::pair<double,double> Diagram_point;
     
    template < template<typename E, typename = std::allocator< E > > class ContainerT >
    class PersistenceDiagram{
     
    public:
      typedef ContainerT< Diagram_point > Container;
      typedef typename Container::const_iterator Diagram_point_iterator;
     
    private:
      Container points;
     
    public:
      PersistenceDiagram(){
          points = Container();
      }
     
      void add_point(Diagram_point p){
          points.push_back(p);
      }
     
      Diagram_point_iterator begin(){
          return points.cbegin();
      }
     
      Diagram_point_iterator end(){
          return points.cend();
      }
    };
    �a marche. Il n'y a plus qu'un unique fichier vu que c'est un template. Merci � tous.

    Edit : Sauf avec les std::set forc�ment vu qu'ils ont besoin d'un comparator.

  9. #9
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    D�tails du profil
    Informations personnelles :
    Localisation : France, Paris (�le de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par d�faut
    Pas mal cette technique de rebind de type ! Voil� comment je l'utiliserais:

    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
    #include <vector>
     
    struct unused_type;
     
    template <typename New, typename Unused> struct rebind_type;
     
    template <typename New, typename Unused, typename ... Args>  struct rebind_type<New, std::vector<Unused, Args...>> {
      using type = std::vector<New, Args...>;
    };
     
    template <typename DataType, typename Container> class SelfContainer {
      using container_type = typename rebind_type<SelfContainer*, Container>::type;
      DataType value_;
      container_type children_;
     public:
      SelfContainer() {};
      SelfContainer(DataType const& value) : value_(value) {}
      void AddChild(SelfContainer* child) { children_.push_back(child); }
    };
     
    int main() {
      SelfContainer<int, std::vector<unused_type> > c1;
      SelfContainer<int, std::vector<unused_type> > c2;
      c1.AddChild(&c2);
      return 0;
    }
    Le probl�me �tait de pouvoir cr�er une classe template pouvant agr�ger des pointeurs vers des instances de la m�me classe. Je n'avais pas r�ussi sans template template, c'est maintenant chose faite.

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Bonne pratique des templates - Container
    Par LittleWhite dans le forum C++
    R�ponses: 5
    Dernier message: 04/09/2012, 17h55
  2. Diff�renciation array <> container dans un template
    Par Trademark dans le forum Langage
    R�ponses: 8
    Dernier message: 17/08/2011, 01h39
  3. Template, Container Sequence, Vector et Deque
    Par Ange44 dans le forum Langage
    R�ponses: 5
    Dernier message: 30/07/2010, 17h30
  4. fonction template pour container
    Par Bourrine dans le forum Langage
    R�ponses: 8
    Dernier message: 26/06/2007, 13h55
  5. [XSLT] template
    Par demo dans le forum XSL/XSLT/XPATH
    R�ponses: 4
    Dernier message: 09/09/2002, 11h31

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