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 :

Utilisation de templates


Sujet :

C++

  1. #1
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut Utilisation de templates
    Bonjour, j'aimerais faire un vecteur trié. cependant, j'obtiens quelques problèmes au niveau de la spécialisation des templates pour les pointeurs.

    Voici ce que j'ai fait jusqu'à présent et qui ne gère pas cette aspect :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    template<typename Object, typename Sort,class Storing=std::list<std::pair<Object*,Sort>>>
    class Sorted
    {
        private :
            Storing List;
        public :
            Sorted()=default/*J'utilise c++0x*/;
            Sorted(const Sorted&)=delete;
            Sorted& operator=(Sorted&)=delete;
            ~Sorted()=default;
            void AddElement(Object* Element, Sort Position);
            inline void EraseElement(Object* Element);
            inline void ForEach(void (Object::*Function)(void));
    };
    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
    template<typename Object, typename Sort, class Storing>
    inline void Sorted<Object, Sort, Storing>::AddElement(Object* Element, Sort Position)
    {
        typename Storing::iterator it;
        for(it=List.begin();it!=List.end();it++)
            if(it->second<=Position)
                break;
        List.insert(it,std::make_pair(Element,Position));
    }
     
    template<typename Object, typename Sort, class Storing>
    void Sorted<Object, Sort, Storing>::EraseElement(Object* Element)
    {
        for(auto/*J'utilise c++0x*/ it=List.begin();it!=List.end();it++)
        {
            if(it->first==Element)
            {
                List.erase(it);
                return ;
            }
        }
    }
     
    template<typename Object, typename Sort, class Storing>
    inline void Sorted<Object, Sort, Storing>::ForEach(void (Object::*Function)(void))
    {
        for(auto it=List.begin();it!=List.end();it++)
            (it->first->*Function)();
    }
    Mon problème :

    -Cette classe ne marche pour l'instant que si Object est un pointeur et si sort n'est pas un pointeur. Comment adapté pour que sa marche dans tous les cas ?
    -D'autres problèmes ? (Peut être on peut faire un Storing = std::list sans spécifier les template de la liste ? ce qui permettrais, si on veut un vector de juste passer un std::vector et non std::vector<std::pair<...>>)

    J'espère que le code est assez explicite pour comprendre ce que la classe fait (c'est un conteneur trié).

    Merci de votre aide.

  2. #2
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Au lieu d'untilsier un pointeur de fonction, utilise un parametere tempalte non spécifié, ca te permetrra deja de pas te hardcoder sur les types de la fonctions.

    Ensuite, pourquoi passe tu un pointeur sur objet ?

  3. #3
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Au lieu d'untilsier un pointeur de fonction, utilise un parametere tempalte non spécifié, ca te permetrra deja de pas te hardcoder sur les types de la fonctions.
    Pas de problème la dessus, je vais le changer.

    Ensuite, pourquoi passe tu un pointeur sur objet ?
    Parce que dans l'utilisation principale que j'en fait, c'est un pointeur de fonction virtuelle que j'utilise.


    La classe telle quelle est me suffit très largement pour l'utilisation minimale que j'en fait. Ce que j'aimerais faire, c'est la rendre utile pour d'autres projets (être le plus générique possible).

  4. #4
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Pas de problème la dessus, je vais le changer.
    En fait, je rencontre un petit problème :

    Si je fais un template<typename Fc>, il faudrait spécialiser si c'est une fonction membre ou pas : si Fc est une Fonction membre, j'appelle la fonction comme en haut, sinon j'appelle la fonction comme sa Function(*(it->first));

    Comment gérer cette différence de syntaxe ? Un boost ou std::bind ? Un lambda ?

  5. #5
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    bind avec le *this ou bien utilisez un traits pour detecter si Fc est un member_function_pointer et spécialiser selon.

  6. #6
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    bind avec le *this ou bien utilisez un traits pour detecter si Fc est un member_function_pointer et spécialiser selon.
    Ok, c'est ce que je pensais.

    Me reste toujours un gros problème : comment spécialiser dans le cas ou object est un pointeur et si possible de ne pas avoir à spécifier les template de Storing. Il me faudrait juste la syntaxe pour écrire la classe : google ne semble pas vouloir lâcher les réponses...

  7. #7
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    bind avec le *this ou bien utilisez un traits pour detecter si Fc est un member_function_pointer et spécialiser selon.
    Je viens de régler le problème ainsi :

    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
    template<typename Fc, typename Obj, typename R, typename ...Args>
    struct CallFunction
    {
        inline static R Call(Fc Function, Obj& Object, Args...Arguments)
        {
            return Function(Object, Arguments...);
        }
     
    };
     
    template<typename Obj, typename R, typename ...Args>
    struct CallFunction<R(Obj::*)(Args...),Obj,R,Args...>
    {
        inline static R Call(R(Obj::*Function)(Args...), Obj& Object, Args...Arguments)
        {
            return (Object.*Function)(Arguments...);
        }
    };
    Cependant, mes 2 autres problèmes persistent (au passage semblerait que gcc considère que
    void (truc::*)(void) n'est pas du même type que
    void(truc::*)()

  8. #8
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Tous mes problèmes sont quasiment réglés, cependant, reste un dernier problème : Si l'utilisateur veut utilisé un conteneur n'utilisant pas de allocator( donc pas de la STL), comment faire ?

    Voici le code du 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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    template<typename Object, typename Sort,template<typename, typename>class Storing=std::list>
    class Sorted
    {
        private :
            Storing<std::pair<Object, Sort>, std::allocator<std::pair<Object, Sort>>> List;
        public :
            Sorted()=default;
            Sorted(const Sorted&)=delete;
            Sorted& operator=(Sorted&)=delete;
            ~Sorted()=default;
            void AddElement(Object Element, Sort Position);
            inline void EraseElement(Object Element);
            template<typename Fc>
            inline void ForEach(Fc Function);
    };
     
    template<typename Object, typename Sort,template<typename, typename>class Storing>
    class Sorted<Object*, Sort, Storing>
    {
        private :
            Storing<std::pair<Object*, Sort>, std::allocator<std::pair<Object*, Sort>>> List;
        public :
            Sorted()=default;
            Sorted(const Sorted&)=delete;
            Sorted& operator=(Sorted&)=delete;
            ~Sorted()=default;
            void AddElement(Object* Element, Sort Position);
            inline void EraseElement(Object* Element);
            template<typename Fc>
            inline void ForEach(Fc Function);
    };
    Comment faire pour utiliser les template par défaut de la STL ?
    Pour ne pas avoir à préciser template<typename,typename> class Storing : Si il n'y a qu'un paramètre template ?

  9. #9
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Ne passe pas de paramètres template template mais un simple parametre template et utilise des traits ou des concepts pour valider la correction de ton appel.

  10. #10
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Ne passe pas de paramètres template template mais un simple parametre template
    Je perds alors en simplicité : l'utilisateur doit faire std::vector<std::pair<...,...>> alors que dans le cas actuel, l'utilisateur n'est même pas au courant de l'utilisation de std::pair.

    Je viens d'y penser, 2 autres spécialisations ne régleraient-elles pas le problème ?

  11. #11
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    Bonjour, j'aimerais faire un vecteur trié.
    Un multiset ne correspondrait pas à tes attentes ?

    Steph.

  12. #12
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Un multiset est un peu trop lourd pour le peu que j'en fait. De plus, il ne présente pas l'avantage du ForEach (implémentable si agrégation).
    Je prévois d'étendre cette classe mais uniquement dans les méthodes et en les gardant très basique (je prévois une option d'accéder aux éléments) et etc...

  13. #13
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    D'accord.

  14. #14
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    Je perds alors en simplicité : l'utilisateur doit faire std::vector<std::pair<...,...>> alors que dans le cas actuel, l'utilisateur n'est même pas au courant de l'utilisation de std::pair.

    Je viens d'y penser, 2 autres spécialisations ne régleraient-elles pas le problème ?
    Perso je passerais un constructeur meta-lambda, et ton Storing aurait comme parametere supplementaire le type de pair à utiliser.

    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
     
    template<class Container, class Pair = std::pair<mpl::_1,mpl::_2>
    struct Storing
    {
    private :
      typedef typename mpl::apply2<Pair,Object,Sort>::type pair_type;
      typedef typename mpl::apply1<Container, pair_type>::type data_type;
     
      data_type List;
     
     // etc ...
    };
     
    typedef Storing< std::vector<mpl::_> > store_vector;
    typedef Storing< std::list<mpl::_>, tuple<mpl::_1,mpl::_2> > store_list_with_tuple;
    En interne, passe par les at_c de boost::fusion et tu gère tout les cas sans passer par un type concret. Ca rend ton design indépendant du type de pair (on peut y mettre un tuple ou tt autre séquence fusion) et ca régle ton probleme de parametrage.

Discussions similaires

  1. [XSLT] Utilisation variable template
    Par mihaestii dans le forum XSL/XSLT/XPATH
    Réponses: 10
    Dernier message: 23/11/2005, 15h44
  2. Probleme d utilisation de template dans le cpp
    Par Math75 dans le forum Langage
    Réponses: 2
    Dernier message: 07/10/2005, 16h26
  3. Utilisation des templates
    Par mikky dans le forum C++
    Réponses: 1
    Dernier message: 14/09/2005, 12h59
  4. Fuite de mémoire en utilisant le template list
    Par schtroumpf_farceur dans le forum Langage
    Réponses: 9
    Dernier message: 18/07/2005, 20h44
  5. Utilisation de template dans un role de fonctions/procedures
    Par Punky65250 dans le forum XSL/XSLT/XPATH
    Réponses: 14
    Dernier message: 01/09/2004, 10h05

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