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 :

Instantiation implicite de templates


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2007
    Messages : 60
    Par défaut Instantiation implicite de templates
    Bonjour,

    J'ai une classe template A qui contient un champ de données membre statique x. Y-a-t'il un moyen de s'assurer que A<T>:: x va être réellement instancié (ie. symbole créé dans le fichier objet), pour toute instantiation implicite de A. On garantit qu'un objet de type A<T> est créé.

    Exemple :

    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
    // a.hpp
    template<typename T>
    struct A {
      unsigned x;
     
      A();
    };
     
    template<typename T>
    unsigned A<T>::x;
     
    // a.tpp
    #include "a.hpp"
     
    template<typename T>
    inline A<T>::A() {
      // quelque chose ici pour forcer A<T>::x
    }
     
    // a.cpp
    #include "a.hpp"
    #include "a.tpp"
     
    A<int> objet;
     
    // b.cpp
    #include "a.hpp"
     
    // contrat : A<int> instancié quelque part
    int main() {
      std::cout << A<int>::x << std::endl;
      return 0;
    }
    Pour l'instant j'ai tenté le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T>
    inline A<T>::A() {
      unsigned* u = &A::x;
      (void)u; // pas de warning
    }
    Il fonctionne (a.o continent bien A<int>:: x), pour une compilation avec "g++ -O0", mais le symbole disparaît dès que l'optimisation est activée ("g++ -O1" suffit) .

    Avec-vous une quelconque idée ?

    Cordialement,

    Camille

  2. #2
    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 : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Il est vrai que je viens de passer plusieurs heures sur une réponse et que je dois donc tout doucement commencer à fatiguer, mais...

    A moins que je n'ai vraiment pas les yeux en face des trous, il n'y a aucun membre statique dans ta structure

    Erreur de copier / coller, ou oubli réel dans ton code

    Pour déclarer un membre statique dans une structure, il faut utiliser le mot clé static, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template<typename T>
    struct A {
      static unsigned x;
     
      A();
    };
     
    template<typename T>
    unsigned A<T>::x = valeurParDefaut;
    Et, à ce moment là, x sera bel et bien créé dans chaque fichier d'implémentation dans lequel tu as une instanciation de A

    Note toutefois que static implique que le membre est "global" dans l'unité de compilation dans laquelle il se trouve.

    Il n'est donc pas forcément impossible que, pou un T donné, tu te retrouves au final avec plusieurs A<T>: répartis dans les différentes unités de compilation dans lesquelles tu aura utilisé A en lui founissant T en paramètre template

    Note aussi que, ne le rendant pas privé dans le cas présent, tu t'expose à ce que "tout et n'importe quoi", y compris les fonctions qui ne disposent pas d'un objet de type A<T>, aille en modifier la valeur à "n'importe quel moment"...

    Ce n'es clairement pas une situation idéale car au final, cela se rapproche très fort d'une variable globale, et tu sais ce qu'on en pense généralement

    Peut etre devrais tu revoir ce point pour t'éviter quelques déboires
    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. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2007
    Messages : 60
    Par défaut
    Désolé, pour le static, c'est juste une erreur de copier-coller.
    De même, le "template<...> unsigned A<T>:: x" devrait se trouver dans a.tpp.

    Je connais les risques associés aux globales ; le but réel serait de créer une sorte de constante de classe dépendant de T, calculée dans a.cpp ; puis lue dans un b.cpp, qui n'a accès qu'à la déclaration de la classe A<T>.

  4. #4
    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 : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    A ce moment là, tu ferais beaucoup mieux d'encapsuler un tout petit peu A<T>:: x, de manière à ce qu'il ne soit effectivement utilisé que dans a.tpp.

    Si tu le rend constant, cela n'aura pas beaucoup d'importance, mais, à moins qu'il ne s'agisse aussi d'une erreur de copier/coller, A<T>:: x n'est pas constant, et donc, susceptible de changer à beaucoup d'endroit.

    Avec un x constant, tu peux sans problème laisser l'initialisation dans a.hpp et ne pas trop t'en faire pour l'encapsulation, sous une forme proche de
    a.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template<typename T>
    struct A
    {
        static const int x;
    };
    template <typename T>
    int A<T>::x = 153;
    car, à ce moment là, toute unité de compilation qui inclue a.hpp de manière directe ou indirecte disposera de sa propre valeur pour A<NimporteQuoi>:: x, qui sera le même dans toutes les unités de compilations

    Par contre, si A<T>:: x n'est pas constant, il faut veiller à ce que son utilisation ne sorte pas de l'unité de compilation dans laquelle il est effectivement utilisé

    Tu pourrais, par exemple, le faire passer dans l'accessibilité privée et rendre une fonction amie, pour qu'elle puisse en profiter, sous une forme proche de
    a.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template <typename T>
    class A
    {
        friend void foo(/* ...*/);
        private:
            static int x;
    };
     
    void foo(/*...*/);
    a.tpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template <typename T>
    int A<T>::x = 32;
    /* ...*/
    a.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include <a.hpp>
    #include <a.tpp>
    void foo(/* ... */)
    {
       int i = A<Truc>::x;
       /* ... */
    }
    voire, en C++11, profiter de la possibilité d'avoir des template amies
    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

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2007
    Messages : 60
    Par défaut
    Merci pour les conseils, mais tu t'attaches à l'encapsulation, qui n'est pas du tout le problème ici.

    La question est en fait : étant donné un type T fixe, quel code faut-il écrire dans a.cpp pour que le symbole A<T>:: x soit accessible depuis b.cpp qui n'inclut pas la définition de A<T>:: x ?

    Après, peu importe qui accède, ou comment, du moment que le symbole est généré.

    Dans le cas général, je sais qu'une instantiation explicite suffit. Mais si je me restreins à une instantiation implicite et un appel de fonction membre ?

    C'est une question théorique sur l'instantiation template en fait.

  6. #6
    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 : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Ce que tu ne sembles pas comprendre, c'est que toute la différence tient dans le fait que x est constant ou non...

    Si c'est "simplement" une constante pure et dure, tu peux sans problème la définir dans ton fichier d'en-tête, car elle sera construite pour chaque implémentation de A<T> que tu pourras faire, dans chaque unité de compilation qui en a besoin, et l'on peut très bien se "foutre éperdument" du fait que cette constante se trouve dans XXX fichiers objet : si elle s'y trouve, c'est que chaque fichier objet utilise une instanciation de A<T> et qu'il en avait donc besoin.

    Par contre, si x n'est pas une constante (et c'est ce que montre ton code, à moins qu'il ne s'agisse d'une erreur de copier coller !!!), alors, il faut savoir que cette variable a une valeur qui est propre à l'unité de compilation qui l'utilise.

    Tu pourrais très bien en arriver à une situation pour le moins dangereuse où Truc.cpp qui instancie A<Truc> se trouve occupé à utiliser A<Truc>:: x avec un valeur de 12, alors que Machin.cpp utilise lui aussi A<Truc> mais dans lequel A<Truc>:: x a une valeur de 126

    C'est une situation pour le moins fragile, tu en conviendras

    C'est la raison pour laquelle j'attire ton attention sur le fait qu'il faut savoir exactement ce que tu attends de A<T>:: x et sur les options qui s'offrent à toi

    C'est d'autant plus vrai que si Truc.cpp instancie A<Truc>, tu cours le risque (selon l'ordre dans d'appel de tes fonctions) qu'une fonction machin qui se trouve dans Machin.cpp essaye d'accéder à A<Truc>:: x alors que la variable n'a pas encore été créée
    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

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

Discussions similaires

  1. Meta-programation, template et cast implicite
    Par Awakening dans le forum C++
    Réponses: 15
    Dernier message: 10/02/2012, 19h03
  2. [template]Résolution implicite d'un type template
    Par ZeeByeZon dans le forum Langage
    Réponses: 4
    Dernier message: 23/07/2010, 15h04
  3. déduction implicite d'argument template
    Par camboui dans le forum C++
    Réponses: 12
    Dernier message: 13/06/2010, 20h41
  4. template et conversion implicite
    Par bolhrak dans le forum Langage
    Réponses: 3
    Dernier message: 10/11/2007, 13h17
  5. Réponses: 2
    Dernier message: 02/08/2005, 11h44

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