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


Sujet :

Langage C++

  1. #21
    Membre Expert

    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 : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    @koala: La norme autorise un programme a contenir plusieurs fois la définition d'une fonction membre d'une classe template comme l'indique l'extrait que j'ai cité (mais toujours une seule fois pas unité de compilation et sous réserve que les définitions des différentes unités de compilation soient identiques), pas besoin de inline, si ton compilateur te donne un "multiple definition of" dans ce contexte, alors c'est un bug de celui-ci.

  2. #22
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    C'est quoi ta définition de inline? Parce que je pense que le problème est là.
    Une fonction inline est une fonction qui dont le symbole au niveau du binaire peut se retrouver dans plusieurs unités de compilation (ou, si tu préfères dont on peut retrouver une implémentation dans plusieurs unités de compilation, avec la garantie que l'implémentation est identique partout) et dont l'appel peut être remplacé par le code correspondant de la fonction.

    C'est donc exactement la définition de la norme . Mais il me semble que tu bloques essentiellement sur une partie de la définition de inline :
    oui, bien sur, le compilateur peut (devrait préférer, d'après la norme) décider de remplacer l'appel de la fonction par le code correspondant, tout en gardant la possibilité de générer le code binaire de la fonction de manière "tout à fait classique" dans l'unité de compilation où elle apparait (en gros, lorsqu'il génère le code binaire de n'importe quel fichier cpp qui inclut d'une manière ou d'une autre l'implémentation de cette fonction) et d'utiliser le mécanisme d'appel "classique".

    Sur ce point, nous semblons être tout à fait d'accord . Le problème est ce qui se passe après que le compilateur ait fini son travail, au moment où l'éditeur de liens prend le relais.

    En effet, à l'éditeur de liens part -- pour n'importe quelle fonction -- du principe que l'ODR est respecté et t'engueule s'il trouve deux symboles identiques dans deux unités de compilation parce que ce n'est justement pas le cas (c'est ce qui se passe quand un débutant décide d'inclure un fichier .cpp dans un autre, par exemple).

    Il y a donc forcément un mécanisme qui permet au compilateur d'indiquer dans le fichier objet qu'il génère une information indiquant à l'éditeur de liens qu'"il se peut que tu trouves le symbole équivalent à cette fonction dans d'autre unités de compilation... je compte sur toi pour faire le ménage" (en gros, ce que tu viens de réexpliquer )

    Mais l'éditeur de liens n'est pas plus malin que n'importe quel autre outil de la chaine de compilation : si on ne lui donne pas l'ordre de faire quelque chose, il ne le fera pas d'avantage que le compilateur ou que le préprocesseur... Si le compilateur génère le code binaire d'une fonction dans plusieurs unités de compilation (soit parce que c'est une fonction inline qu'il a décidé de ne pas inliner, soit parce que l'implémentation d'une fonction non inline se retrouve "par erreur" incluse dans différentes unités de compilation), et que le compilateur ne lui a rien dit, il t'engueulera au motif que "le symbole est défini plusieurs fois".

    Et de son coté, le compilateur est un tout aussi brave petit soldat que l'éditeur de liens : il ne fera jamais quelque chose si on ne lui a pas dit de le faire. On ne doit donc pas s'attendre à ce qu'il indique à l'éditeur de liens qu'il doit faire le ménage dans un fichier objet si on ne lui a pas demandé de le faire!!!

    Or, le seul moyen de demander au compilateur de laisser ce message à l'éditeur de liens, c'est de passer par une fonction inline. Car, jusqu'à preuve du contraire, tous les compilateurs que je connais "oublient" ce qu'ils ont généré dans une unité de compilation lorsqu'ils passent à une autre (ce qui fait que, en pratique, un modèle de compilation qui utiliserait une db d'une manière ou d'une autre n'est pas applicable "en l'état") .
    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

  3. #23
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Une fonction inline est une fonction qui dont le symbole au niveau du binaire peut se retrouver dans plusieurs unités de compilation (ou, si tu préfères dont on peut retrouver une implémentation dans plusieurs unités de compilation, avec la garantie que l'implémentation est identique partout) et dont l'appel peut être remplacé par le code correspondant de la fonction.

    C'est donc exactement la définition de la norme .
    Citations SVP. Ma lecture de la norme est qu'une série de fonctions sont déclarées comme inline et que les fonctions inlines ont des propriétés. Le fait que d'autres fonctions partagent certaines propriétés n'en fait pas des fonctions inlines. Un exemple stupide: si on finit par ajouter de l'introspection de manière à pouvoir savoir si une fonction est inline, l'introspection devra retourner false pour ces autres fonctions quel que soit le nombre de propriétés qu'elles ont en commun avec les fonctions formellement inline. Par contre une fonction qui est formellement inline, devra retourner true, même si par nature elle n'est présente que dans une seule unité de compilation (p.e. l'opérateur () d'une lambda ou une fonction statique ou définie dans un namespace privé), même si aucun de ses appels n'est inliné.

    Mais il me semble que tu bloques essentiellement sur une partie de la définition de inline :
    Ce sur quoi je bloque est le renversement de causalité. La norme indique que certaines fonctions sont inlines et que les fonctions inlines ont certaines propriétés. Faire de ces propriétés la définition des fonctions inlines ne me va pas. D'autres fonctions (les instances de templates p.e.) peuvent avoir ces propriétés sans être inline.

    Or, le seul moyen de demander au compilateur de laisser ce message à l'éditeur de liens, c'est de passer par une fonction inline.
    A ma connaissance, les seuls éditeurs de liens qui ont une notion d'inline sont ceux qui sont capables de faire l'optimisation correspondante. Pour jeter les définitions dupliquées de fonctions inlines ou d'instances de templates, le compilateur communique en utilisant d'autres concepts, les mêmes qui leur permettent aussi de fusionner les common en Fortran ou les définitions de variables sans initialisations et vraisemblablement de faire d'autres choses pour d'autres langages.

    Car, jusqu'à preuve du contraire, tous les compilateurs que je connais "oublient" ce qu'ils ont généré dans une unité de compilation lorsqu'ils passent à une autre (ce qui fait que, en pratique, un modèle de compilation qui utiliserait une db d'une manière ou d'une autre n'est pas applicable "en l'état")
    Je t'assure que le compilateur C++ de Sun était (ça fait des années depuis la dernière fois que j'ai regardé) avait une db contenant les instanciations de templates déjà faites. Ce qui avait des avantages mais apportait son lot de problèmes quand il fallait utiliser des outils conçus en ignorant cette possibilité. Visual age d'IBM (je ne l'ai pas utilisé dans ce mode) était aussi capables d'utiliser une db me semble-t'il (pour d'autres choses -- dont de l'inline entre CU --, avec d'autres problèmes). Et si on sort du C et de C++, les compilateurs Ada -- je crois que GNAT est le premier à faire autrement -- utilisaient aussi des DB et je parie que c'est le cas pour d'autres langages (SmallTalk est le premier que je regarderai s'il faut en citer d'autres).

  4. #24
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Vienne (Limousin)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Octobre 2014
    Messages : 6
    Par défaut
    Bonjour, et désolé pour le fait de répondre longtemps après...
    Tout d'abord, merci beaucoup pour toutes vos réponses!
    Alors, pour vous donner une idée, l'architecture de ce que je voudrais faire ressemble à ça(en ne gardant que les idées):
    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
    template <class T>
    class M<T> {
        virtual void foo(T);
    };
     
    class T{
        virtual void function();
    };
     
    class t1: public T {
        virtual void function() {
            // corps de la fonction
        }
        void plop();
    };
     
    class t2: public T {
        virtual void function() {
            // corps de la fonction
        }
        void plip();
    };
     
    class m1: M<t1>{
        void foo(t1 param) {
            param.plop();
        }
    };
     
    class m2: M<t2>{
        void foo(t2 param) {
            param.plip();
        }
    };
    Donc, cela permettrait - côté client - d'exécuter un code du style du suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    int main(int argc, char** argv) {
        T* t;
        t = new t1;
        m1* m = new m1; // ou alors
        m1* m = new M<t1>;
        m1->foo(*t);
    }

  5. #25
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Spirine Voir le message
    Alors, pour vous donner une idée, l'architecture de ce que je voudrais faire ressemble à ça
    Quel problème rencontres-tu?

    À part des choses qui tiennent plus de la faute de frappe et de la distraction, je ne vois rien qui soit lié aux templates. Le seul problème conceptuel important (s'il n'est pas la conséquence d'une schématisation trop rapide) est que le mélange d'une sémantique de valeur avec l'utilisation de virtuelles. Ç'est conceptuellement boiteux, et souvent source de surprises (une copie vers le type de base fait que la virtuelle appelée n'est pas celle désirée p.e.)

Discussions similaires

  1. Spécialisation de template particulière
    Par Flo. dans le forum Langage
    Réponses: 4
    Dernier message: 25/03/2009, 22h18
  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