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 :

Instanciation de fonction template et temporaire


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Par défaut Instanciation de fonction template et temporaire
    Bonjour,

    Je me demande pourquoi mes compilateurs (gcc 4.3, et cl de visual c++ 2005) m'instancie cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void f(int & val)
    {
       std::cout << val << std::endl;
    }
    dans ce cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <iostream>
     
    template<typename T>
    void f(T & val)
    {
       std::cout << val << std::endl;
    }
     
    int main()
    {
       f(int(0));
    }
    Forcément, avec cette instanciation le code ne peux pas compiler.
    Pourquoi le compilateur n'instancie pas cette fonction quand on lui passe un temporaire ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void f(int const & val)
    {
       std::cout << val << std::endl;
    }
    Avec ce comportement, mes compilateurs m'obligent à fournir deux versions de fonction template pour gérer le cas du temporaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<typename T>
    void f(T & val)
    {
       std::cout << val << std::endl;
    }
    template<typename T>
    void f(T const & val)
    {
       std::cout << val << std::endl;
    }
    Y'a t il un moyen de factoriser ce genre de code ?

    ps : ma fonction f n'est qu'un exemple ultra simplifié ... et effectivement dans ce cas précis la version const suffirait, mais ma question porte sur le cas général

  2. #2
    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
    Par défaut
    Bonjour,
    Je vais répondre de biais :
    1/si tu n'as pas besoin de modifier val, pourquoi déclarer la version non const ? Sachant qu'il existe (dans boost) des moyens de supprimer le qualificateur const s'il est déjà présent dans T.
    2/ Si tu as besoin de modifier val, alors c'est que tu dois distinguer les 2 comportements.

  3. #3
    Membre émérite Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Par défaut
    En fait il faut prendre f comme une fonction générique au sens ou elle est indépendante du fait que t soit const ou pas.
    Elle appelle seulement des fonctions sur t, et dans T ses fonctions ont des version const et non const (*).

    Peut être que je peux donner un exemple si mon explication n'est pas assez concrète ...

    (*) : ou pas, et dans ce cas le compilateur pourra effectivement se plaindre de façon justifiée . Par exemple si on passe un temporaire à f et que seules les fonctions non const sont définies dans T.

  4. #4
    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
    Par défaut
    Citation Envoyé par MatRem Voir le message
    En fait il faut prendre f comme une fonction générique
    Ma réponse était générique

    Citation Envoyé par MatRem Voir le message
    Elle appelle seulement des fonctions sur t, et dans T ses fonctions ont des version const et non const (*).
    Soit la fonction suppose qu'elle ne modifie pas l'objet, donc elle n'est supposée qu'appeler des fonctions const et alors le paramètre doit être aussi en const.

    Citation Envoyé par MatRem Voir le message
    Peut être que je peux donner un exemple si mon explication n'est pas assez concrète ...
    Je veux bien. Ca éclairera peut être un peu plus le besoin.

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Que se passe-t-il si tu tentes d'invoquer explicitement f<const int>(0) ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre émérite Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Par défaut
    Voiilà un exemple qui permet de comprendre le principe.
    Par contre il ne compile pas puisque je ne fournis pas les deux versions de f et que j'utilise un temporaire (c'est fait exprès pour bien voir que dans ce cas je ne devrais pas avoir besoin de fournir les deux) :

    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
    template<typename T>
    void f(T & t)
    {
       t.call_the_right_function();
    }
     
    struct S
    {
       void call_the_right_function();
       void call_the_right_function() const;
    };
     
    int main()
    {
       f(S()); //Ne compile pas
     
       S const s;
       f(s); //compile trés bien puisque la fonction instanciée est bien void f(T const &)
     
       f<S const>(S()); //fonctionne aussi trés bien
    }

Discussions similaires

  1. Réponses: 2
    Dernier message: 02/10/2008, 16h37
  2. Fonction template virtuelle... comment l'éviter ?
    Par :Bronsky: dans le forum Langage
    Réponses: 12
    Dernier message: 07/06/2005, 14h21
  3. fonctions template
    Par romeo9423 dans le forum Langage
    Réponses: 12
    Dernier message: 22/01/2005, 16h13
  4. Fonctions et tables temporaires ?!
    Par devdev dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 16/12/2004, 11h46
  5. Fonctions template+friend sous VC7
    Par patapetz dans le forum MFC
    Réponses: 12
    Dernier message: 24/09/2004, 11h16

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