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 :

template et précompilateur


Sujet :

Langage C++

  1. #1
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut template et précompilateur
    Salut à tous.
    Voici une petite classe template de test qui me pose problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    template<int THREAD_SUPPORT>
    struct machin {
       machin() {
       #if (THREAD_SUPPORT==0)
       cout << "no thread support" << endl;
       #else
       cout << "thread support" << endl;
       #endif
       }
    };
    Le but est de pouvoir choisir si on désire protéger l'objet par un mutex ou pas. C'est une question de facilité d'utilisation, c'est pour une petite biblio qui doit être la plus simple possible à utiliser, je voudrais rendre le support multithread optionel pour ne pas toujours être obligé de linker avec les binaires de boost::thread. Mais je voudrais aussi pouvoir utiliser des versions multithread et non multithread de cette classe dans le même programme si nécessaire, question d'optimisation.
    L'ennui c'est que ce code va systématiquement afficher "no thread support", même si je passe 1 en paramètre template. Donc mes questions sont:
    - est-ce qu'il est possible d'utiliser une constante de template en conjonction avec le précompilateur, comme j'essaie de le faire (je me souviens plus, j'ai toujours calé un peu sur les templates)
    - si oui, qu'est-ce qui cloche dans mon code?
    Merci d'avance.

  2. #2
    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 zais_ethael
    - est-ce qu'il est possible d'utiliser une constante de template en conjonction avec le précompilateur,
    Non.

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Non.
    Bon ben comme ça je suis fixé

  4. #4
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut
    Salut,

    Je ne pense pas que tu puisses faire ce que tu veux, les templates étant résolu à la compilation, qui intervient après le preprocessing.
    [EDIT] : grilled

    Sinon tui peux aussi paramétrer ta structure par une classe gérant le comportement multithread, et fournir un paramètre par défaut, du style :

    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
     
    template <class MultiThreadingPolicy = NoMultiThreading>
    struct machin : private MultiThreadingPolicy {
     
        machin() {
            MultiTHreadingPolicy::lock(bidule_a_lock);
        }
    };
     
    class NoMultiThreading {
     
        public:
            template <class Lockable>
            void lock(const Lockable& lockable) {
            }
     
    };
     
    class MultiThreading {
     
        public:
            template <class Lockable>
            void lock(const Locakble& lockable) {
                //dépend de la plateforme su laquelle tu es et/ou de la lib que tu utilises
                la_fonction_qui_lock(lockable);
            }
    }
    Le code est juste opur illustrer le principe, après ça dépend comment tu souhaites synchroniser tout ça.

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    J'ai fait quelques tests.
    Reprenons l'exemple précédent un peu modifié:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    template<int THREAD_SUPPORT>
    struct machin {
       machin() {
       if (THREAD_SUPPORT==0) {
          //rien
       } else {
          /* plein de fonctions de manipulation de mutexs
          et qui nécéssitent forcément de lier la librairie correspondante
          au link */
       }
       }
    };
    Comme vous pouvez le constater, je n'utilise plus de commandes de précompilation mais un test à exécuter au runtime.
    J'ai fait une ou deux observations:
    - si je compile avec support multithread en liant boost::thread, ça fonctionne
    - si je compile avec support multithread sans lier boost::thread, forcément j'ai des erreurs au link
    - si je compile sans support multithread et sans lier boost::thread, ça fonctionne, en dépis du fait qu'après précompilation le code contient des appels de fonctions sans implémentations (mais qui ne seront jamais appelées, le if/else oblige)
    Ma supposition est que Mingw, voyant une structure alternative utilisant une constante, va optimiser mon code en zappant le cas impossible à atteindre, donc c'est "comme si" ce bout de code n'existait pas.
    Donc la tout de suite ça me convient mais je crains un peu pour la portabiblité

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Ca n'a pas l'air terrible comme solution (même pas sûr que cela en soit une vraie), celle à base de policy donnée par bolhrak sera bien meilleure. Enfin l'idée est là, quoi.

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Dans le cas qui me préocupe, ce serait encore plus simple de faire comme ceci:
    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
     
    struct machin_threadé {
       machin_threadé() {
          /* plein de fonctions de manipulation de mutexs */
       }
    };
     
    struct machin_pas_threadé {
       machin_pas_threadé() {
          //rien
       }
    };
     
    #ifdef THREAD_SUPPORT
    typedef machin machin_threadé
    #else
    typedef machin machin_pas_threadé
    #endif
    Je n'ai pas besoin d'une gestion de police, juste d'un truc binaire.
    Cela dit, avec cette solution précise je ne sais pas si, même en n'utilisant jamais la classe machin_threadé dans mon code, le linker ne va pas nécéssiter quand même la liaison avec boost::thread. Et puis je trouvais la solution à base de template assez élégante

  8. #8
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Il faut commencer par savoir de quoi tu as besoin.

    Si tu n'as besoin qu'une d'une version de ta classe dans tout le programme, alors les solutions à base de préprocesseur seront les bonnes. Avoir deux versions de la classe et choisir la bonne avec un #if est une bonne méthode, mais c'est encore mieux si tu ne compiles pas du tout la classe inutile (là elle va être compilée mais jamais utilisée).

    Si tu as besoin de manipuler les deux versions dans un même programme, alors les templates seront la meilleure solution, tu pourras choisir à chaque instanciation si tu veux ou non le support du multithreading. Là encore, en codant bien tu peux t'arranger pour ne compiler que ce qu'il faut à chaque fois.

    Mais j'ai plutôt l'impression que tu te trouves dans le premier cas.

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Citation Envoyé par Laurent Gomila
    Mais j'ai plutôt l'impression que tu te trouves dans le premier cas.
    Non (oui, je suis difficile). En fait je voudrais pouvoir faire comme dans mon troisième cas, choisir entre machin_threadé, machin_pas_threadé ou alors machin (dont la signification dépend d'une constante globale).

    Citation Envoyé par Laurent Gomila
    Si tu as besoin de manipuler les deux versions dans un même programme, alors les templates seront la meilleure solution, tu pourras choisir à chaque instanciation si tu veux ou non le support du multithreading. Là encore, en codant bien tu peux t'arranger pour ne compiler que ce qu'il faut à chaque fois.
    Ben non justement, c'est ce que j'essaie de faire dans la première solution, mais apparament je suis bien obligé de faire figurer le code des mutexs "quelque part", le problème est le même dans la solution de bolhrak.

  10. #10
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Bon, visiblement, quand je définis la classe suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    struct machin_threadé {
       machin_threadé() {
          /* plein de fonctions de manipulation de mutexs */
       }
    };
    et que je ne l'instancie nulle part, le linker ne rale pas. Reste juste à savoir si le comportement sera le même sur tous les compilos (je ne suis pas sur que si je n'instancie pas une classe ayant été définie, le compilateur ne va pas quand même compiler cette classe et la filer au linker).

  11. #11
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Les templates (classe ou fonction) ne sont compilés qu'à l'instanciation. Si tu n'instancies pas, tu ne compiles pas. Ca porte un nom que j'ai oublié d'ailleurs.

  12. #12
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Ok, je vais faire comme ça alors.
    Merci à ceux qui m'ont répondu.

  13. #13
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Effectivement, la question la plus importante à te poser est : à quel moment est résolue ta variabilité (*):
    * une seule fois, et cela se fait au niveau projet ; dans un cas particulier comme le multi-threading, alors un bon gros #ifdef des familles fera l'affaire bien mieux que n'importe quoi d'autre

    * des bouts de code avec et des bouts sans, et c'est statiquement sûr au niveau du code => les templates, c'est bien pour ça. Que cela soit
    - en politiques (code plus explicite, façon paramètre),
    - en mixin-layer (code plus explicite, façon couches d'onions)
    - en mappant des constantes entières à des types

    * dynamiquement => change ton approche.

    (*) Je ne serai pas étonné que Coplien parle de cela (cela == Binding Time) dans la thèse qui précède son bouquin Multi-Paradigm Design for C++ => Le seul lien simple à retrouver que j'ai trouvé.
    C'est ça, §3.5
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

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

Discussions similaires

  1. [Templates] Quel système utilisez-vous ? Pourquoi ?
    Par narmataru dans le forum Bibliothèques et frameworks
    Réponses: 270
    Dernier message: 26/03/2011, 00h15
  2. Template XHTML
    Par Sylvain James dans le forum XSL/XSLT/XPATH
    Réponses: 14
    Dernier message: 16/06/2003, 21h45
  3. appliquer plusieurs templates
    Par Manu_Just dans le forum XSL/XSLT/XPATH
    Réponses: 7
    Dernier message: 04/04/2003, 16h26
  4. template match="node() mais pas text()"
    Par Manu_Just dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 26/03/2003, 10h52
  5. [XSLT] template
    Par demo dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 09/09/2002, 11h31

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