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 :

bug de specialisation template avec fichiers séparés


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut bug de specialisation template avec fichiers séparés
    Bonjour,
    J'ai le code suivant :

    Fichier.h
    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
    #include <iostream>
    struct A
    {
        template < typename Unknown >
        void eval ( Unknown x ) const;
    };
     
    template < typename Unknown >
    void A :: eval ( Unknown x ) const
    {
        std::cout << "eval x = " << x () << std::endl;
    }
     
    template <>
    void A :: eval< int > ( int x ) const
    {
        std::cout << "specialisation eval x = " << x << std::endl;
    }
    Fichier.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include "Fichier.h"
     
    int main()
    {
        A a;
        a.eval(2);
     
        return 0;
    }
    Lorsque je compile, j'obtiens le message suivant du compilateur :
    multiple definition of `void A::eval<int>(int) const'

    Cependant si je met l'intégralité de Fichier.h dans Fichier.cpp, le code compile parfaitement et se comporte parfaitement (à savoir appel du membre spécialisé).

    Comment faire pour résoudre le problème en gardant les 2 fichiers?

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    N'y a-t-il pas un souci de déclaration #include dans ton .cpp ?...

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut
    J'ai reformulé le problème pour enlever le code inutile, j'ai donc fait une faute de frappe dans le #include, désolé.
    J'ai édité le poste.

    Sinon, le code compile avec le vieux hack du mot clé inline, mais il y a bien une solution ne faisant pas appel à ce hack?

  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
    Par défaut
    Salut,
    Citation Envoyé par backlash Voir le message
    Sinon, le code compile avec le vieux hack du mot clé inline, mais il y a bien une solution ne faisant pas appel à ce hack?
    Ce n'est pas un hack et c'est même un objectif de ce mot clé. Je pense que Fichier.h est inclus dans plusieurs .cpp, d'où ton problème. A peu de chose près, ton problème est strictement équivalent à
    Code fichier.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifndef FICHIER_H
    #define FICHIER_H
    #include <iostream>
    struct A
    {
        void eval ( int x ) const;
    };
     
    void A :: eval( int x ) const
    {
        std::cout << "specialisation eval x = " << x << std::endl;
    }
    #endif // FICHIER_H

    Code toto.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    #include "fichier.h" // et rien de plus dans ce .cpp

    Code main.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include "fichier.h"
    int main()
    {
    return 0;
    }

    Ce code provoque l'erreur de lien car la fonction void A :: eval( int x ) const se trouve définie dans plusieurs unité de compilation (.cpp), donc dans plusieurs .obj et le linker râle. LA solution est bien de passer par le mot clé inline dont l'objectif n'est pas seulement d'indiquer une préférence pour l'inlining mais aussi de dire au compilo de ne définir qu'une seule fois la fonction.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut
    @Archi3D : J'ai l'impression que Matthieu Brucher avance le contraire.

    Le post:http://www.developpez.net/forums/d58...tion-template/

    Dans sa réponse, il dit qu'il faut déclarer le prototype de la méthode, cependant vu que la fonction est template, il n'est pas possible de déclarer un prototype pour les versions spécialisées, d'ailleurs en réfléchissant cela semble incensé, non?

    J'ai essayé de mettre la définition de la version spécialisé dans le fichier .cpp associé au .h, mais cette fois ci le compilateur n'utilise pas la version spécialisée de la méthode template mais la version template avec résolution des types. Ce qui provoque évidemment un bug à la compilation car l'opérateur () n'est pas défini pour le type primitif int.

    Le code :

    Fichier.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <iostream>
     
    struct A
    {
        template < typename Unknown >
        void eval ( Unknown x ) const;
    };
     
    template < typename Unknown >
    void A :: eval ( Unknown x ) const
    {
        std::cout << "eval x = " << x () << std::endl;
    }
    Fichier.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "Fichier.h"
     
    template <>
    void A :: eval< int > ( int x ) const
    {
        std::cout << "specialisation eval x = " << x << std::endl;
    }
    main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include "Fichier.h"
     
    int main()
    {
        A a;
        a.eval(2);
     
        return 0;
    }
    Et les erreurs :
    In file included from ..\src\main.cpp:10:
    ..\src\Fichier.h: In member function 'void A::eval(Unknown) const [with Unknown = int]':
    ..\src\main.cpp: instantiated from here
    ..\src\Fichier.h: error: 'x' cannot be used as a function

  6. #6
    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
    Par défaut
    Salut,

    Je ne sais pas ce que pensait Mathieu, mais je ne pense pas qu'il s'agisse d'un hack.

    Sinon, faut le faire à l'extérieur de la classe :
    Code fichier.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    struct A
    {
        template < typename Unknown >
        void eval ( Unknown x ) const;
    };
     
    template < >
    void A :: eval<int>( int x ) const;
     
    template < typename Unknown >
    void A :: eval ( Unknown x ) const
    {
        std::cout << "eval x = " << x () << std::endl;
    }

    Code fichier.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "fichier.h"
     
    template <>
    void A :: eval< int > ( int x ) const
    {
        std::cout << "specialisation eval x = " << x << std::endl;
    }

    Code main.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include "fichier.h"
    #include <cstdlib>
     
    int main()
    {
        A a;
        a.eval(2);
        a.eval(rand);
     
        return 0;
    }

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

Discussions similaires

  1. [PHP 5.2] Bug avec fichier de traduction
    Par jimmyneutron dans le forum Langage
    Réponses: 0
    Dernier message: 27/05/2014, 17h13
  2. [Templates] Difficultés avec moteur de templates et fichiers CSS
    Par CompuTux dans le forum Bibliothèques et frameworks
    Réponses: 0
    Dernier message: 03/10/2011, 21h35
  3. Réponses: 5
    Dernier message: 24/09/2007, 16h43
  4. [Débutant] Popup avec javascript dans un fichier séparé
    Par Marco85 dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 20/12/2006, 17h28
  5. Réponses: 4
    Dernier message: 25/08/2003, 09h02

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