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 :

Pb. bizarre avec g++ et une "struct template"


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut Pb. bizarre avec g++ et une "struct template"
    Bonsoir à tous,

    Voilà je suis tombé sur ce comportement bizarrre de g++ (mingw) lors de la définition / spécialisation d'une struct template.

    Généralement j'évite ce genre de code, (j'ai d'ailleurs 2/3 workarounds), mais il se trouve que pour l'implémentation de traits, une struct est suffisament simple (il s'agit de regrouper sous un même élément plusieurs fonctions).

    Toujours est-t'il que le compilo me jettes à la compilation.

    Une idée ?
    Si quelqu'un pouvait essayer de compiler les fichiers sur sa machine pour voir si le pb. est reproductible, ça serait sympa.
    Fichiers attachés Fichiers attachés

  2. #2
    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
    Hello,

    La définition de la méthode zero() doit être dans le même fichier que sa déclaration (ou un fichier inclus après sa déclaration), comme n'importe quelle fonction d'une classe template, même s'il s'agit d'une spécialisation totale.

    Seules les données statiques d'une spécialisation totale doivent être définies dans un cpp (pour éviter une erreur de link), pas les fonctions.

  3. #3
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Salut,

    Merci pour cette précision.
    J'avais effectivement un problème avec mes fichiers.
    Par contre chose bizarre, j'ai réussi à compiler correctement en déplaçant la spécialisation totale traits<floating_t>::zero() dans le fichier TraitsSpec.cpp (fichier de corps et pas fichier d'entête).

    Donc l'explication que tu m'as donné n'est pas tout à fait juste.

    Cette solution est pas terrible car j'aurais vraiment voulu laisser la spécialisation floating_t de zero() dans le fichier Test.cpp. L'idée étant que la définition générale soit dans Traits.tpl.h, quelques spécialisations de base dans TraitsSpec.cpp, et les spécialisations "utilisateur" supplémentaires dans Test.cpp. D'ailleurs ce genre de répartition fonctionne très bien avec des fonctions templates (pas des méthodes).

  4. #4
    Membre Expert
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Par défaut
    Salut,

    j'ai compilé en supprimant la spécialisation dans Test.cpp (elle était déjà dans TraitsSpec.cpp)

  5. #5
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Citation Envoyé par coyotte507 Voir le message
    Salut,

    j'ai compilé en supprimant la spécialisation dans Test.cpp (elle était déjà dans TraitsSpec.cpp)
    Le problème c'est que traits<floating_t> est différent de traits<double>, car C++ considère floating_t et double comme 2 types différents.

    Tu n'as qu'à lancer le .exe compilé après tes modifs. pour t'en rendre compte (exception).

  6. #6
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Finalement j'ai résolu le pb.

    Code Test.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #ifndef TestH
    #define TestH
     
    #include "Traits.h"
     
    typedef double floating_t;
     
    floating_t traits<floating_t>::zero();
     
    void test_function();
     
    #endif // TestH

    Il suffisait de faire une déclaration "en avant" des méthodes templates ou lieu de la classe template.

  7. #7
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Citation Envoyé par mchk0123 Voir le message
    Le problème c'est que traits<floating_t> est différent de traits<double>, car C++ considère floating_t et double comme 2 types différents.
    ....
    Je me suis trompé là dessus. floating_t et double sont la même chose pour le compilateur une fois le typedef fait.

    Donc si on remplace "floating_t" par "float", la compilation passe avec la déclaration forward de spécialisation de la méthode template, mais pas avec la déclaration forward de la spécialisation de la struct template. C'est ça que je n'arrive pas à comprendre.

    Voilà le code :
    Fichiers attachés Fichiers attachés

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Par défaut
    Salut,

    Le problème majeur que je vois dans ton code est que tu spécialises totalement ta structure traits pour les doubles (dans le fichier Test.h) alors que dans le fichier TraitsSpec tu spécialises seulement zero() pour les doubles. Or normalement si tu décides de spécialiser une fonction membre d'une classe pour un type particulier tu ne peux plus ensuite définir de spécialisation de cette classe pour ce type. Dans ton cas le compilateur ne peut pas détecter le problème à la compilation puisque ton programme est découpé en plusieurs unités de compilation. Le problème survient donc seulement à l'édition de lien. Pour solutionner le problème je déclarais dans le fichier Traits.h les deux spécialisation de zero() 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
    19
    20
    #ifndef TraitsH
    #define TraitsH
     
    template<typename T>
    struct traits {
      static T zero();
    };
     
    template<>
    double traits<double>::zero();
     
    template<>
    unsigned long traits<unsigned long>::zero();
     
     
    #ifndef TraitsBody
    #  include "Traits.tpl.h"
    #endif // TraitsBody
     
    #endif // TraitsH
    Ainsi si quelqu'un essaie de spécialiser traits pour un des types double ou unsigned long alors le compilateur pourra détecter l'erreur et émettre un diagnostic.

    PS: Dans ton fichier Test.cpp tu mets template<> devant la définition de zeros() or ce n'est pas correct puisque auparavant tu as défini un spécialisation totale de ta struct traits pour les doubles (ton code ne passe la compilation avec gcc 4.3.0)

  9. #9
    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
    Citation Envoyé par mchk0123 Voir le message
    Salut,

    Merci pour cette précision.
    J'avais effectivement un problème avec mes fichiers.
    Par contre chose bizarre, j'ai réussi à compiler correctement en déplaçant la spécialisation totale traits<floating_t>::zero() dans le fichier TraitsSpec.cpp (fichier de corps et pas fichier d'entête).
    Donc tu te retrouves bien dans le cas ou déclaration et définition sont dans le même fichier

    J'ai effectivement sous-entendu de manière implicite dans ma première réponse que la déclaration était dans un header, ce qui n'est pas obligatoire. Rien n'empêche de déclarer et définir une classe template locale à une unité de compilation.

  10. #10
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Par défaut
    @mchk0123: Ton code ne compile toujours pas avec gcc 4.3.0 ni avec Visual C++ 2005. Donc je doute que ton problème soit réellement résolu.

Discussions similaires

  1. Update avec variable contenant une quote
    Par NejNej dans le forum Développement
    Réponses: 2
    Dernier message: 13/11/2009, 17h51
  2. Problème bizarre avec une variable de type string
    Par beegees dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 10/06/2009, 11h34
  3. Pb bizarre avec un CAST dans une PS
    Par Arnaud_B dans le forum Développement
    Réponses: 4
    Dernier message: 22/04/2009, 20h08
  4. [TP] Problème bizarre avec une boucle
    Par Dunk dans le forum Turbo Pascal
    Réponses: 5
    Dernier message: 10/12/2006, 14h06

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