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 :

Templates et specialisation


Sujet :

C++

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 12
    Points : 8
    Points
    8
    Par défaut Templates et specialisation
    Bonjour,

    J'ai le code suivant :

    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
    template<typename T>
    T FromString(const std::string & Str, bool & Res)
    {
       T Dest = T();
       std::istringstream iss( Str );
       Res = iss >> Dest != 0;
       return Dest;
    }
     
    template<>
    bool FromString<bool>(const std::string & Str, bool & Res) 
    {
    	bool Dest = false;
    // Trucs differents
    	return Dest;
    }
    Pb, vraisemblablement à cause de la signature, j'obtiens des pbs au link (code déjà défini).
    Comment faire dans une situation pareille lorsque le type de template n'apparait pas en passage de paramètres ?

    Je veux pouvoir faire des
    int toto = FromString<int>(...);
    bool toto = FromString<bool>(...);
    La bonne fonction étant automatiquement appelée...

    Merci pour vos remarques

  2. #2
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Il faut rajouter le mot clef inline si je ne m'abuse.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 13
    Points : 35
    Points
    35
    Par défaut
    Citation Envoyé par robosara Voir le message
    Bonjour,



    Pb, vraisemblablement à cause de la signature, j'obtiens des pbs au link (code déjà défini).
    Comment faire dans une situation pareille lorsque le type de template n'apparait pas en passage de paramètres ?

    Je veux pouvoir faire des
    int toto = FromString<int>(...);
    bool toto = FromString<bool>(...);
    La bonne fonction étant automatiquement appelée...

    Merci pour vos remarques
    J'ai l'impression, que tu dois inclure ta spécialisation ( et sa définition...) dans de multiples fichiers sources, et elle doit se retrouver dans de multiples fichiers objets.

    Parce que ton code compile sans problème de link.

    Essaies en déclarant uniquement ( ta spécialisation) dans ton fichier header, et la définissant dans un fichier source unique.

  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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Il faut rajouter le mot clef inline si je ne m'abuse.
    Tu ne t'abuses pas.
    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
    template<typename T>
    inline T FromString(const std::string & Str, bool & Res)
    {
       T Dest = T();
       std::istringstream iss( Str );
       Res = iss >> Dest != 0;
       return Dest;
    }
     
    template<>
    inline bool FromString<bool>(const std::string & Str, bool & Res) 
    {
    	bool Dest = false;
    // Trucs differents
    	return Dest;
    }

  5. #5
    screetch
    Invité(e)
    Par défaut
    hmmm j'aurait dit static au lieu de inline
    disons pour être pedantic (comme GCC) que l'effet recherché s'obtient avec static, et que inline marche aussi, avec l'effet supplémentaire d'inliner la fonction

    or l'effet demandé a l'origine c'est "static" non?

    de toutes facons j'aurais mis static inline si le code est assuez court =)

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par screetch Voir le message
    hmmm j'aurait dit static au lieu de inline
    disons pour être pedantic (comme GCC) que l'effet recherché s'obtient avec static, et que inline marche aussi, avec l'effet supplémentaire d'inliner la fonction

    or l'effet demandé a l'origine c'est "static" non?

    de toutes facons j'aurais mis static inline si le code est assuez court =)
    Non... l'effet demandé est bel et bien celui de inline!

    Le mot clé static ne déroge pas au respect de l'ODR (One Definition Rule), et son effet dépend des circonstances.

    Dans le plus complexe des cas, tu l'utilise sur une fonction membre d'une classe template sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template <typename T>
    class MyClass
    {
        public:
             static void foo(MyClass const &)
             {
                  /*...*/
             }
    };
    qui va te permettre d'utiliser la fonction sans avoir besoin d'en créer une instance (c'est le but de static ) mais qui, surtout, sera implicitement déclarée inline parce que définie au sein meme de la définition de la classe en question!

    Si tu voulais d'ailleurs sortir la définition de la fonction de la classe, tu devrais avoir un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template <typename T>
    class MyClass
    {
        public:
             static void foo(MyClass const &);
    };
     
    inline void MyClass::foo(MyClass const &)
    {
        /*...*/
    }
    C'est en effet le seul moyen pour que l'éditeur de liens ne s'étonne pas de trouver plusieurs implémentations de fonctions représentées par le même symbole, car, en dehors de toute instanciation explicite, il ne faut pas oublier que le compilateur ne pourra créer le code binaire correspondant à la fonction que... lorsqu'il saura par quel type effectif remplacer T !!!

    Il est donc tout à fait possible que tu te retrouve, le compilateur travaillant comme il le fait, dans une situation où tu auras une implementation de MyClass<int>::foo dans XXX.cpp et une autre dans YYY.cpp, simplement pare que le compilateur "oublie" ce qu'il a pu faire entre XXX.cpp et YYY.cpp, à charge pour l'éditeur de liens de "remettre de l'ordre".

    Il n'est pas exclus, si la fonction n'est pas effectivement inlinée, que l'éditeur de liens ne corrige les symboles appelés et ne fasse en sorte qu'il n'y ait pour finir qu'un code binaire de la fonction correspondante, mais seul le mot clé pourra le prévenir qu'il doit agir de la sorte
    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

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2010
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 12
    Points : 8
    Points
    8
    Par défaut
    Merci à tous pour vos réponses.

    Ca fonctionne bien en mettant le "inline" au bon endroit

  8. #8
    screetch
    Invité(e)
    Par défaut
    je suis pas d'accord avec toi pour le coup;
    on parlait de fonctions libres, pas de fonctions de classe, donc je parlais de la version "C" de static.

  9. #9
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par screetch Voir le message
    je suis pas d'accord avec toi pour le coup;
    on parlait de fonctions libres, pas de fonctions de classe, donc je parlais de la version "C" de static.
    Avec inline, le compilateur accepte de voir plusieurs définition identique de la fonction mais celle ci n'est réellement présente qu'une seule fois dans l’exécutable (voir aucun si c'est inliné à chaque fois).

    Avec static, la fonction n'est visible que de l'unité de compilation courante, elle peut donc être visible plusieurs fois par le compilateur sans souci. Par contre il existera potentiellement plusieurs exemplaire du code de cette fonction dans l'exécutable final.

    Dans les deux cas, sauf réglage particulier du compilateur, la fonction sera inlinée ou non en fonction des critères de décision du compilateur (il n'a pas l'obligation d'inlinée une fonction inline ni l'interdiction de le faire sur d'autres fonctions).
    En C++ on utilise un namespace anonyme plutôt que static.

  10. #10
    screetch
    Invité(e)
    Par défaut
    je veux bien un lien ou une preuve =)

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par screetch Voir le message
    je veux bien un lien ou une preuve =)
    lix.polytechnique.fr :
    static functions are functions that are only visable to other functions in the same file.
    Le problème avec les fonctions template, c'est que le compilateur a impérativement besoin du code C++ pour générer le code binaire correspondant car chaque fois qu'il va utiliser T, il devra prévoir plus ou moins de place si T est un char, un int ou n'importe quel type personnel

    Du coups, la définition de la fonction se trouvant dans le fichier d'en-tête, la dite fonction serait visible partout où le fichier est inclus, de manière directe ou indirecte...

    Le bénéfice du mot clé static (dans son acception C du terme) est donc nul, ou peut s'en faut

    En outre, il faut vraiment que ni le compilateur ni l'éditeur de liens ne s'étonne de trouver potentiellement plusieurs (ou aucune) fois la définition de la fonction
    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

  12. #12
    screetch
    Invité(e)
    Par défaut
    toujours pas d'accord, je crois que tu fais une mauvaise interpretation du mot-clé static
    moi je pense que static est le mot-clé qui justement dit au compilateur qu'on pourrait avoir plusieurs définitions (le symbole devient "weak", aux yeux du linker);
    et je pense que inline est le mot clé qui dit "essaye d'inliner le code la ou on l'appelle", ce qui implique que le code risque d'être défini plusieurs fois, mais c'est un effet de bord de inline, pas l'effet principal

    et donc je pense toujours que static est le mot clé qui est la réponse la plus juste

  13. #13
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Concernant le static, voir le §3.5 de la norme (en fait du draft n3290) :

    When a name has internal linkage , the entity it denotes can be referred to by names from other scopes in the same translation unit.
    A name having namespace scope (3.3.6 ) has internal linkage if it is the name of
    — a variable , function or function template that is explicitly declared static;
    Une fonction static a un internal linkage et donc n'est visible que dans le scope de l'unité de compilation courante (c'est l'effet premier du static, et c'est similaire à l'utilisation d'un namespace anonyme).
    La conséquence de ceci c'est que deux fonctions static (identique ou non) de même prototype peuvent exister tant qu'elles sont dans des unité de compilations différentes (et donc l'utilisation de static fonctionne bien ici).

    Concernant inline, voir le § 7.1.2, point 4

    An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case (3.2). If the definition of a function appears in a translation unit before its first declaration as inline, the program is ill-formed. If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears ; no diagnostic is required. An inline function with external linkage shall have the same address in all translation units. A static local variable in an extern inline function always refers to the same object.
    A string literal in the body of an extern inline function is the same object in different translation units.
    A type defined within the body of an extern inline function is the same type in every translation unit.
    Donc une fonction inline peut donc être présente dans plusieurs unité de compilation (doit même s'il elle est utilisée dans différentes) et il s'agit d'une seule et unique fonction (même adresse dans toutes les unités de compilation).

    Concernant l'inlining des fonctions inline, §7.1.2 point 2 :

    A function declaration ( 8.3.5 , 9.3, 11.3 ) with an inline specifier declares an inline function . The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions de fined by 7.1.2 shall still be respected.
    Le compilateur n'a pas l'obligation d'inliner une fonction déclarée inline, par contre il doit respecter les autres points, dont la règle sur la définition multiple de fonctions inline.

    Concernant la possibilité d'inliner une fonction static, il s'agit simplement de la règle qui dit que le compilateur a le droit de faire ce qu'il veut tant que le comportement visible reste conforme.


    D'une manière générale, le rôle du mot clé inline est de plus en plus (tout du moins dans ce que je peux voir) de permettre la définition multiple (quelqu'en soit l'origine : visibilité dans les différentes unité de compilation pour favoriser l'inlining, tentative d'avoir des bibliothèques header only, utilisation de template, etc.) que de demander l'inlining au compilateur (il est bien meilleurs que le développeur moyen pour se rendre compte s'il y a un gain)

  14. #14
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    @screetch : Comme autre source que la norme directement comme te le propose gl, tu peux lire l'annexe A du Vandevoorde sur l'ADR (je résume ce que le livre donne) :

    Les fonctions inline peuvent être définies plusieurs fois dans différentes unités de compilation (pas dans la même), mais elles doivent contenir la même séquence de "token" et ils doivent avoir la même signification (*) (pas forcément trivial dans tout les cas).

    Ceci doit permettre au compilateur d'assurer l'unicité de l'addresse de la fonction dont parle le 7.1.2 (si c'est pas respecté c'est un UB).

    Le cas de static permet de créer des variables dont la visibilité est locale à l'unité de compilation. Ils sont cas du concept "d'internal linkage", comme les namespace anonyme.

    (*) Il y a une petite "exception" je te laisse voir.

Discussions similaires

  1. Class template et specialisation d'operateur
    Par alex.buisson dans le forum Langage
    Réponses: 2
    Dernier message: 22/04/2013, 16h10
  2. specialisation de template
    Par camboui dans le forum Langage
    Réponses: 2
    Dernier message: 29/01/2009, 14h16
  3. [Template] specialisation de classe template
    Par vandamme dans le forum Langage
    Réponses: 3
    Dernier message: 19/10/2008, 14h22
  4. specialisation de fonction template
    Par chubinou dans le forum Langage
    Réponses: 8
    Dernier message: 13/11/2007, 14h03
  5. Réponses: 5
    Dernier message: 29/12/2005, 21h27

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