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 & syntax


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut Template & syntax
    Hello,

    Je voudrais faire une fonction template dont le paramètre template que je lui enverrai à l'instanciation serait un typedef sur un map :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef std::map<int,double> MonMapAMoi;
    En template, mon map serait de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<KeyT, ElementT>
    Je me trouve dans une classe dont des données membres vont me permettre dans getKey de déduure une valeur de clé que j'utiliserai ensuite sur le map.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <...>
    KeyT MaClasse::getKey() const
    {
        return (une valeur de clé pour le map);
    }
    L'instanciation dépend du type de map que je veux filer à cette fonction. Je peux donner MonMapAMoi comme paramètre de type, mais comment faire en sorte que le lien soit fait entre le type de map passé en paramètre, et la valeur de retour KeyT correspondante ?

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 625
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 625
    Points : 30 674
    Points
    30 674
    Par défaut
    Salut,

    "tout simplement" en définissant, à l'intérieur de ta classe, un typedef le type "key_type" du paramètre template...

    !!! Cela implique qu'il faudra que le paramètre template dispose du type adéquat (qu'il s'agisse d'un set ou d'une map) !!!

    Mais on peut s'en sortir grace à la spécialisation

    Voici un code de démo qui du part principe que, quoi qu'il arrive, ce sera toujours une std::map qui sera utilisée (dont on ne sait simplement pas quels sont les types de valeur et de clé )

    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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    #include <iostream>
    #include <map>
    template <typename T>
    class MyClass
    {
        public:
        typedef typename T::key_type key;
        typedef typename T::value_type value;
        typedef typename T::const_iterator const_iterator;
        typedef typename T::iterator iterator;
        template <typename iter >
        MyClass(iter b, iter e):data_(b,e){}
        key getKey(/*...*/) const
        {
            std::cout<<"try to find the key"<<std::endl;
            /* je ne prend que le premier élément, pour la démo ;) */
            const_iterator it = data_.begin();
            return it->first;
     
        }
        value const & findValue(key k) const
        {
            return data_.find(k)->second;
        }
        const_iterator begin() const{return data_.begin();}
        const_iterator end() const{return data_.end();}
        const_iterator find(key k){return data_.find(k);}
        private:
            T data_;
     
    };
    int main()
    {
        /* par facilité uniquement */
        typedef std::map<int, double> map;
        std::map<int,double> tab;
        tab.insert(std::make_pair(1, 1.22));
        tab.insert(std::make_pair(4, 3.22));
        tab.insert(std::make_pair(3, 3.1415));
        tab.insert(std::make_pair(110, 10.22));
        MyClass<map> mc(tab.begin(),tab.end());
        std::cout<<"getKey renvoie : "<<mc.getKey()<<std::endl;
        for(MyClass<map>::const_iterator it = mc.begin();it!=mc.end();++it)
            std::cout<<"iterateur obtenu "<<it->first<<" = "<<it->second<<std::endl;
        return 0;
    }
    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

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    J'ai dû mal poser mon problème.

    La méthode déterminant la valeur que doit renvoyer getKey() est dépendante du type, mais les valeurs employées pour faire le calcul dépendent d'un contexte extérieur.

    En fait, j'ai une classe globale qui définit, en imbriqué, les trois types que j'aimerais utiliser comme argument template. Mais la méthode getKey() doit se faire au niveau de la classe englobante.

    En fait, la question est d'abord : comment imposer qu'un argument template soit un map, si on n'utilise pas ce map dans la liste des arguments ou dans la valeur de retour de la fonction ?

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 625
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 625
    Points : 30 674
    Points
    30 674
    Par défaut
    Pourrais tu poster le code complet qui te pose problème

    C'est à dire :
    1. Le code de la fonction
    2. le code de la classe d'où est extraite la fonction
    3. le code de la (ou des) classes qui est (sont) nécessaire(s) à la classe, et qui interviennent dans la fonction
    Parce que je ne comprend absolument pas ce que tu essaye de faire, ni ce qui est fait pour l'instant
    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

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    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
    34
    35
    36
    37
    class MainClass
    {
        class A {...};
        class B {...};
     
        typedef std::map<unsigned int, std::vector<A> > AMap;
        typedef std::map<unsigned long int, std::vector<B> > BMap;
     
        AMap mapOfA;
        BMap mapOfB;
     
        template <...>
        KeyT getKey()
        {
            // la valeur renvoyée dépend de value1 et/ou value2 et/ou value3
            // selon le type de map, tout comme la méthode employée pour
            // déterminer la clé
        }
     
        int value1;
        int value2;
        int value3;
     
        void process(std::vector<A>& elements)
        {
            key = getKey<AMap>();
            AMap::iterator = mapOfA.find(key);
            ...
        }
     
        void process(std::vector<B>& elements)
        {
            key = getKey<BMap>();
            BMap::iterator = mapOfB.find(key);
            ...
        }
    };
    Je crois que tout y est...

    Le but ultime est ensuite de templatiser process()...

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Je pensais avoir trouvé une solution en mettant dans chaque classe le type de clé correspondant, et en faisant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename KeyT>
    KeyT getMapKey<MainClass::A, KeyT>()
    {
    	MainClass::::KeyType foo;
    	return foo;
    }
    La déduction automatique m'aurait permis de me passer de donenr le second type, mais j'avais oublié que la spécialisation partielle n'est pas possible pour les méthodes...

  7. #7
    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
    Bonjour.

    Citation Envoyé par oodini Voir le message
    En fait, la question est d'abord : comment imposer qu'un argument template soit un map, si on n'utilise pas ce map dans la liste des arguments ou dans la valeur de retour de la fonction ?
    Je ne sais pas si le problème est toujours d'actualité, mais avec les type traits, on devrait pouvoir s'en sortir, non ?
    Quitte à les faire soi-même...

    Code Un exemple : 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 <map>
     
     
    template <typename T>
    struct is_map
    {
        typedef T type;
        typedef typename type::key_type key_type;
        typedef typename type::mapped_type mapped_type;
        typedef typename type::value_type value_type;
    };
     
     
    template <typename T>
    void f()
    {
        typename is_map<T>::type t;
    }
     
     
    int main()
    {
        f< std::map<int, int> >();
        f<int>();
        return 0;
    }
    À la compilation, ça accepte la ligne 23, mais refuse la ligne 24.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    toto.cpp: In instantiation of ‘is_map<int>’:
    toto.cpp:17:   instantiated from ‘void f() [with T = int]’
    toto.cpp:24:   instantiated from here
    toto.cpp:8: error: ‘int’ is not a class, struct, or union type
    toto.cpp:9: error: ‘int’ is not a class, struct, or union type
    toto.cpp:10: error: ‘int’ is not a class, struct, or union type
    toto.cpp: In function ‘void f() [with T = int]’:
    toto.cpp:24:   instantiated from here
    toto.cpp:17: warning: unused variable ‘t’

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Effectivement, je n'avais pas pensé à l'aspect trait du conteneur map.

    Mais vu que ma solution fonctionne, je vais la garder.

    Merci, toutefois !

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

Discussions similaires

  1. Syntaxe fonction template dans classe template
    Par Aleph69 dans le forum C++
    Réponses: 6
    Dernier message: 15/07/2011, 15h32
  2. syntaxe template spécialisation
    Par guillaume07 dans le forum C++
    Réponses: 5
    Dernier message: 31/12/2010, 08h13
  3. [Template] Différentes syntaxes
    Par Opérateur dans le forum C++
    Réponses: 4
    Dernier message: 19/11/2009, 09h47
  4. Réponses: 13
    Dernier message: 29/09/2006, 16h10

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