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

Langage C++ Discussion :

Fonction membre template dans une classe normale et spécialisation partielle


Sujet :

Langage C++

  1. #1
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut Fonction membre template dans une classe normale et spécialisation partielle
    Bonjour à tous.
    Je pense que le titre parle de lui même (), voici donc le code:
    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
     
    #include <vector>
    #include <iostream>
     
    class Foo{
    public:
        template<typename T> static T plop(T val) 
        {
    	return val;
        }
     
        template <class T, template <typename,typename=std::allocator<T> > class C> 
        static C<T> plop(const C<T>& val)
        { 
    	std::cout<<"template conteneur"<<std::endl;   
    	return std::vector<T>(1, val[1]);
        }
     
    };
     
     
    //Plante
    template <class T> std::vector<T> Foo::plop(const std::vector<T>& val) 
    {
        return std::vector<T>(1, val[1]);
    }
     
    template <> int Foo::plop(int val)
    {
        return val*10;
    }
     
    int main(int argc, char const *argv[])
    {
     
        std::cout<<Foo::plop(std::vector<std::string>(3,"Hi world"))[0]<<std::endl;
        std::cout<<Foo::plop("hello")<<std::endl;
        std::cout<<Foo::plop(42)<<std::endl;
        return 0;
    }
    J'ai l'erreur suivante
    b.cpp:53: erreur: prototype for ‘std::vector<T, std::allocator<_Tp1> > Foo::plop(const std::vector<T, std::allocator<_Tp1> >&)’ does not match any in class ‘Foo’
    b.cpp:47: erreur: candidates are: template<class T, template<class, class> class C> static C<T, std::allocator<_Tp1> > Foo::plop(const C<T, std::allocator<_Tp1> >&)
    b.cpp:43: erreur: template<class T> static T Foo::plop(T)
    A la vue de la première ligne, j'ai l'impression qu'il prend la ligne qui plante comme la définition d'une nouvelle fonction et non comme la spécialisation d'une fonction déjà existante. Une idée de comment résoudre ca ?

    Je souhaiterai garder les fonctions membres templates pour garder la déduction automatique du type (même si on peut contourner ce problème avec une fonction membre libre qui est là la base d'une autre solution)
    Merci beaucoup.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  2. #2
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    J'ai dans la tête qu'une spécialisation partielle de fonctions membres est impossible, mais j'y mettrais pas ma main au feu. Faut que je ressorte le bouquin sur les templates.
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  3. #3
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Effectivement c'est impossible, c'est ce qu'on appelle une specialisation partielle de classe template.

    Tu peux spécialiser la classe entièrement, tu peux spécialiser une fonction template entièrement (qu'elle soi membre ou pas) mais tu ne peux pas spécialiser juste une fonction membre d'une classe template (sauf si la dite fonction est template elle même).

  4. #4
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    sauf si la dite fonction est template elle même
    C'est le cas ici, fonction membre template dans une classe "normale" (pas template). Ou alors on ne donne pas le même sens aux mots et c'est génant
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  5. #5
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Je voulais dire qu'a ce moment là tu peux spécialiser la fonction pour les paramettres template de la fonction, mais pas pour ceux de la classe.

    Mais effectivement ici il n'y a que ta fonction membre qui est template.
    (tiens ça compile pas sous Vc9, il trouve pas T dans la déclaration...)


    Après plusieures tentative je n'arrive pas bien a résoudre ton problème, visiblement le paramettre optionel de vector rends la detection de la spécialisation ambigue...

    Le principal problème en fait c'est le fait qu'il y ait deux declaration de plop, la première étant une version plus abstraite de la seconde.
    Pour résoudre ça rapidement j'ai juste ajouté un s a la seconde implémentation voir, mais il y a toujours un problème de detection.

    J'ai essayé ça:

    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
     
    #include <vector>
    #include <iostream>
     
    class Foo{
    public:
    	template<typename T> static T plop(T val) 
    	{
    		return val;
    	}
     
    	template <typename T, template <typename, typename> class C, typename A > 
    	static C<T,A> plops(const C<T, A >& val)
    	{ 
    		std::cout<<"template conteneur"<<std::endl;   
    		return C<T,A>(1, val[1]);
    	}
     
    };
     
     
    //Plante
    template <class T, typename A =std::allocator<T> >
    std::vector<T, A> Foo::plops(const std::vector<T, A>& val) 
    {
    	return std::vector<T, A>(1, val[1]);
    }
     
    template <> int Foo::plop(int val)
    {
    	return val*10;
    }
     
    int main(int argc, char const *argv[])
    {
     
    	std::cout<<Foo::plop(std::vector<std::string>(3,"Hi world"))[0]<<std::endl;
    	std::cout<<Foo::plop("hello")<<std::endl;
    	std::cout<<Foo::plop(42)<<std::endl;
    	return 0;
    }
    Mais j'ai l'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    1>e:\tests\test_templatememberfunctionspecialization\main.cpp(27) : error C2244: 'Foo::plops' : unable to match function definition to an existing declaration
    1>        definition
    1>        'std::vector<_Ty,_Alloc> Foo::plops(const std::vector<_Ty,_Alloc> &)'
    1>        existing declarations
    1>        'C<T,A> Foo::plops(const C<T,A> &)'
    Je ne comprends pas bien ou est le problème, vu que les deux signatures me semblent similaires...

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Les spécialisations partielles de fonctions templates n'existent pas il me semble. Ce sont des surcharges - la différence étant que tu dois la déclarer dans la classe :
    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
    class Foo{
    public:
        template<typename T> static T plop(T val)
        {
    	return val;
        }
     
        template <class T, template <typename,typename=std::allocator<T> > class C>
        static C<T> plop(const C<T>& val)
        {
    	std::cout<<"template conteneur"<<std::endl;
    	return std::vector<T>(1, val[1]);
        }
        template <class T>
        static std::vector<T> plop(const std::vector<T>& val)
        {
            return std::vector<T>(1, val[1]);
        }
    };

  7. #7
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Ah mais oui voilà j'avais mal lu. Je confonds toujours c'est la spécialisation partielle ou l'argument template par défaut dans une fonction template qui est impossible ? (voir les deux? :') )


    edit : je viens de vérifier les deux sont interdits. (default template argument et spécialisation partielle de fonction template)
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  8. #8
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Ok, merci beaucoup, je passe le sujet en résolu.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

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

    Informations professionnelles :
    Activité : aucun

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

    La spécialisation partielle d'une fonction template étant interdite, pourquoi ne pas, tout simplement, créer un foncteur template qui, lui, pourra être partiellement (ou completement) spécialisé

    Le seul bémol à mettre étant que... les différentes implémentations de ce foncteur devront prendre place directement dans la définition de la classe dans laquelle il est imbriqué

    Mais cela donnerait un résultat fort proche de
    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
    class MaClass
    {
        template <typename T>
        sturct Foncteur
        {
            /* blabla*/
        }; 
        template <>
        struct Foncteur<int>
        {
            /*blabla*/ 
        };
        template <typename T, typename U>
        struct AutreFoncteur
        {
        };
        template <typename T>
        struct AutreFoncteur <T, int>
        {
        };
    };
    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

  10. #10
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    C'est la 1er solution que j'évoquais dans mon 1er message, le tout couplé avec une fonction membre libre pour bénéficier de la déduction automatique des types.

    Merci à tous
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

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

Discussions similaires

  1. Réponses: 18
    Dernier message: 01/03/2012, 10h34
  2. Fonction Template dans une classe & Héritage
    Par Drannor dans le forum Langage
    Réponses: 1
    Dernier message: 15/09/2011, 17h20
  3. Membre générique dans une classe ("member template")
    Par damien.flament dans le forum Langage
    Réponses: 13
    Dernier message: 26/08/2010, 07h43
  4. Spécialisation de fonction template dans une class template
    Par summerstorm dans le forum Langage
    Réponses: 6
    Dernier message: 05/01/2010, 20h15
  5. Fonction template dans une classe template
    Par mister3957 dans le forum Langage
    Réponses: 9
    Dernier message: 08/07/2008, 12h11

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