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 de template particulière


Sujet :

Langage C++

  1. #1
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut Spécialisation de template particulière
    Bonjour,

    est-il possible de spécialiser des classes ou des méthodes par rapport à un des types uniquement ?

    Par exemple, imaginons la méthode :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <typename A, typename B> void Method(A a, B b){}
    Si je veux spécialiser par rapport à A quelque soit B, j'ai essayé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <typename B> void Method<int, B>(int a, B b){}
    mais j'obtiens, de la part de g++, un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    erreur: function template partial specialization «Method<float, B>» is not allowed
    Est-ce possible et si oui quelle est la syntaxe ?

    Flo.

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    La simple surcharge peut être une solution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <typename B> void Method(int a, B b){}
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Je ne savais pas qu'on pouvait omettre les types dans l'appel d'une fonction ou d'une classe templatée.

    Donc, effectivement la "simple surcharge" marche, enfin ....

    Imaginons 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 MyClass
    {
    public: 
      template <typename A, typename B> void Test(A a, B b)
      {
        cout << "<typename A, typename B>" << endl;
      }
     
    public:
      template <typename B> void Test(int a, B b)
      {
        cout << "<int, B>" << endl;
      }
    };
     
    template <> void MyClass::Test<float, float>(float a, float b)
    {
      cout << "<float, float>" << endl;
    }
    An niveau de l'appelant, ce code,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main()
    {
      MyClass myClass;
      myClass.Test<float, long>(3.5, 35);
      myClass.Test<int, double>(3.5, 3.5);
      myClass.Test<float>(5, 6.5);
      return 0;
    }
    provoque l'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    main.cpp: In function «int main()»:
    main.cpp:28: erreur: call of overloaded «Test(int, double)» is ambiguous
    main.cpp:7: note: candidats sont: void Toto::Test(A, B) [with A = float, B = double]
    main.cpp:12: note:                 void Toto::Test(int, B) [with B = float]
    Mais par contre, ce code là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main()
    {
      MyClass myClass;
      myClass.Test(3.5, 35);
      myClass.Test(3.5, 3.5);
      myClass.Test(5, 6.5);
      return 0;
    }
    compile et fonctionne très bien.

    J'en viens à 1 question subsidiaire (sans faire du multi-post).

    Comment-ça se fait qu'en donnant plus de détails au compilateur, il n'arrive pas à lever l'ambiguité, alors que le fait de ne rien préciser devrait provoquer des ambiguités ?

    Flo.

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Quand tu dis myClass.Test<float>(5, 6.5);
    Il ne sais pas si tu parles de :
    - template <typename B> void Test(int a, B b) où tu imposes le type de l'argument comme un float
    - template <typename A, typename B> void Test(A a, B b) où tu imposes le type du premier argument comme un float, et celui du second comme étant déduit par l'appel.

    Entre ces deux fonctions (Test<float>(int a, B b) et Test<float, double>(A a, B b)), il doit donc choisir laquelle est la meilleure. Dans le premier cas, il doit convertir un argument de double vers float, dans le second, il doit convertir de double vers int. Les deux conversions ayant le même "coût", il y a ambiguïté. On arrête là le processus de résolution de surcharge.
    A noter que si tu avais appelé Test<float>(5,6.5f) ou bien Test<double>(5, 6.5), tu n'aurais pas eu ce problème.

    Quand tu ne précises pas, il doit choisir entre :
    - template <typename B> void Test(int a, B b) où B est déduit comme étant un doube
    - template <typename A, typename B> void Test(A a, B b) où A est déduit comme un int, et B comme un double.

    Dans les deux cas, il n'y a pas de conversion, donc de ce point de vue là, les deux fonctions sont toutes deux acceptables. Il passe alors au critère suivant, qui est "est-ce que l'une des deux est "moins templatisée" que l'autre. La réponse est oui, et donc template <typename B> void Test(int a, B b) va gagner la résolution de surcharge.

    Je ne sais plus qui disait qu'il ne devait pas y avoir plus de 2/3 personnes au monde à maîtriser les règles de surcharge du C++, mais que ce qui est magique, c'est que dans beaucoup de cas, ça marche sans trop surprendre l'utilisateur. Mais pas dans tous...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    je ne savais pas que le compilateur évaluait autant de choses notamment des règles telles que, en cas d'ambiguité, choisir la fonction la moins templatisée.

    C'est très interessant tout ceci.

    Merci encore. Je ne dirais pas que j'ai tout compris mais j'en sais un peu plus .

    Flo.

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

Discussions similaires

  1. [Problème] Alias de spécialisation de template
    Par DocteurV dans le forum Langage
    Réponses: 9
    Dernier message: 31/08/2009, 17h09
  2. Spécialisation de template parametre avec Enum
    Par 3DArchi dans le forum Langage
    Réponses: 4
    Dernier message: 24/09/2008, 15h21
  3. Spécialisation de template
    Par bobyjoe dans le forum Langage
    Réponses: 18
    Dernier message: 13/12/2007, 21h52
  4. Réponses: 8
    Dernier message: 24/04/2007, 22h09
  5. Réponses: 7
    Dernier message: 01/01/2006, 03h28

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