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 :

Spécialisation partielle d'une fonction template


Sujet :

Langage C++

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 11
    Points : 8
    Points
    8
    Par défaut Spécialisation partielle d'une fonction template
    Bonjour !

    J'essaie de spécialiser une fonction d'une classe template A, dans le cas particulier ou le type est une autre classe template B.
    Je n'arrive pas à savoir si c'est une erreur de syntaxe ou si c'est tout simplement impossible ?
    J'ai essayé de chercher mais je n'arrive pas à formuler ce cas particulier de manière à avoir des résultats... alors toute indice/aide serait bienvenue !

    Merci d'avance !

    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
    class C
    {};
     
    template <class T>
    class B
    {};
     
     
    template <class T>
    class A
    {
    	void foo() {}
    };
     
    template <class T>
    void A<B<T> >::foo() { std::cout << "Allo"; } 
    // error C3860: template argument list following class template name must list parameters in the order used in template parameter list
    // error C2995: 'void A<T>::foo(void)' : function template has already been defined

    EDIT - Auto-Réponse :
    D'après mes recherches donc il est impossible de faire une spécialisation partielle d'une fonction membre.

    Du coup, soit je spécialise manuellement pour chaque sous-type possible (je n'en aurais jamais plus de 3 ou 4 différents)... Soit, je suis à court d'idées la.

  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 : 44
    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
    Mets le corps de tes méthodes dans une structure interne et spécialise cette dernière partiellement. Ensuite dans ta méthode instancie une telle structure et dispatche l'appel.

  3. #3
    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
    Bonjour,
    La question étant assez générique (), tu peux aussi regarder du côté des politiques (cf tutoriel de Alp Présentation des classes de Traits et de Politiques en C++) :
    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
    47
    #include <iostream>
     
    class C
    {};
     
    template <class T>
    class B
    {};
     
     
    template<typename T_>
    struct foo_impl
    {
        static void do_foo()
        {
            std::cout<<"generic foo\n";
        }
    };
     
    template<typename T_>
    struct foo_impl<B<T_> >
    {
        static void do_foo()
        {
            std::cout<<"foo B<T>\n";
        }
    };
     
    template <class T, typename foo_policy_ = foo_impl<T> >
    struct A
    {
        void foo()
        {
            foo_policy_::do_foo();
        }
    };
     
     
    int main()
    {
        A<B<C>,foo_impl<B<C> > >().foo();
        A<B<C> >().foo();
        A<B<C>,foo_impl<C> >().foo();
        A<C,foo_impl<C> >().foo();
     
         return 0;
    }

  4. #4
    Membre habitué Avatar de nowahn
    Homme Profil pro
    Inscrit en
    Août 2008
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 84
    Points : 150
    Points
    150
    Par défaut
    Bonjour,

    Pour répondre d’un point de vue purement syntaxique, sous Linux/g++, il faut apparemment d’abord spécialiser la classe avant de spécialiser la fonction membre avec une classe elle-même template :

    Code C++ : 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
    47
    48
    49
    50
    51
    52
    53
    template <class T>
    class B
    {};
     
    template <class T>
    class A
    {
    public:
       void foo();
    };
     
    // foo() générale
    template <class T>
    void A<T>::foo() { std::cout << "A<T>\n"; }
     
    // foo() spécialisée pour un type non template
    // (pas besoin de spécialiser explicitement la classe)
    template <>
    void A<int>::foo() { std::cout << "A<int>\n"; }
     
    // foo() spécilalisée pour un type template
    // note qu’il y a deux types templates en jeu, donc deux directives « template »
    // le premier template est pour le type A, qui est spécialisé, donc directive vide
    // le deuxième template est pour le type B, qui n’est pas spécialisé
    // la spécialisation explicite de la classe est ici nécessaire
    // (sinon, g++ se plaint de l’utilisation d’un « type incomplet »)
    template <>
    template <class T>
    class A<B<T> >
    {
    public:
       void foo();
    };
     
    template <>
    template <class T>
    void A<B<T> >::foo() { std::cout << "A<B<T> >\n"; }
     
    // test
    int main()
    {
       // 
       A<bool> A1;
       A1.foo();
       // 
       A<int> A2;
       A2.foo();
       // 
       A<B<bool> > A3;
       A3.foo();
     
       return 0;
    }

    Ça implique de recopier entièrement la définition de la classe A, ainsi que la définition de toutes ses fonctions membres, même celles qui sont identique à la classe générale ! (mais ce code compile et fonctionne comme attendu.)
    L’utilisation de politiques comme suggéré par 3DArchi est certainement plus simple dans ce cas.

    Je ne sais pas si ce comportement est conforme à la norme, ou s’il est spécifique à g++, si quelqu’un sait, je suis preneur.

  5. #5
    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
    Bonjour,
    Citation Envoyé par nowahn Voir le message
    Pour répondre d’un point de vue purement syntaxique, sous Linux/g++, il faut apparemment d’abord spécialiser la classe avant de spécialiser la fonction membre avec une classe elle-même template :

    Code C++ : 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
     
    // foo() spécilalisée pour un type template
    // note qu’il y a deux types templates en jeu, donc deux directives « template »
    // le premier template est pour le type A, qui est spécialisé, donc directive vide
    // le deuxième template est pour le type B, qui n’est pas spécialisé
    // la spécialisation explicite de la classe est ici nécessaire
    // (sinon, g++ se plaint de l’utilisation d’un « type incomplet »)
    template <>
    template <class T>
    class A<B<T> >
    {
    public:
       void foo();
    };
     
    template <>
    template <class T>
    void A<B<T> >::foo() { std::cout << "A<B<T> >\n"; }
    Bizarre.
    Dans un premier temps, j'ai cru que tu voulais proposer une spécialisation partielle que j'aurais écrite comme cela :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // spécialisation partielle de A :
    template <class T>
    class A<B<T> >
    {
    public:
       void foo();
    };
    template <class T>
    void A<B<T> >::foo() { std::cout << "A<B<T> >\n"; }
    Code qui compile avec gcc et visual.

    Mais ce que tu proposes ressemble à une spécialisation explicite avec un type générique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template <>
    template <class T>
    class A<B<T> >
    {
    public:
       void foo();
    };
     
    template <>
    template <class T>
    void A<B<T> >::foo() { std::cout << "A<B<T> >\n"; }
    GCC accepte très bien ce code ... mais Visual me jette avec l'erreur C2910.
    En revanche, je n'arrive pas à trouver d'éléments dans la norme indiquant si ta construction est conforme ou pas.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 13/10/2012, 15h02
  2. Réponses: 9
    Dernier message: 24/03/2011, 21h54
  3. retour d'une fonction template
    Par fjxokt dans le forum Langage
    Réponses: 10
    Dernier message: 13/08/2007, 22h29
  4. Pointeur sur une fonction template
    Par Progs dans le forum Langage
    Réponses: 2
    Dernier message: 15/02/2006, 20h25
  5. Réponses: 4
    Dernier message: 29/01/2006, 17h54

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