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 :

Classe générique et problème de multiple définition


Sujet :

C++

  1. #1
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut Classe générique et problème de multiple définition
    Bonjour
    J'ai un problème lors du développement d'une classe j'ai eu à surchargé l'opérateur '==' mais je voudrais surchargé de manière différence si je suis face à un float, double ou long double :
    voici ma classe
    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
    template <class T>
    class A
    {
    T x;
    bool operator==(const A<T>&) const;
    };
     
    template <class T>
    bool A<T>::operator==(const A<T>& a) const
    {
    	return a.x == x;
    }
     
    template <>
    bool A<float>::operator==(const A<float>& a) const
    {
    	return std::abs(a.x - x) <= std::numeric_limits<float>::epsilon();
    }
     
    typedef A<int> iA;
    typedef A<unsigned int> uiA;
    typedef A<short> sA;
    typedef A<long> lA;
    typedef A<float> fA;
    typedef A<double> dA;
    typedef A<long double> ldA;
    Comme vous le voyez à cause des typedef j'ai une multiple définition. Est-ce que vous voyez une solution tout en bénificiant des avantages de la "généricité". Merci

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Points : 122
    Points
    122

  3. #3
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Je n'ai pas d'erreur de compilation sous Comeau Online.

    Mis à part


  4. #4
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut
    [Edit du premier message] j'ai corrigé le class T mais ça ne viens pas de là. La spécification pour float existe pour A<int>, A<unsigned int>, ... Ainsi que pour A<float>, ... Donc normalement ça ne ce compile pas... En tout cas avec g++. Ça compile sans problème sauf au moment du link j'ai :
    obj\Debug\e_Motion_VisionMain.o:: In function `ZNK3eMV8Vector3DIfEeqERKS1_':C:/Documents and Settings/solène/Mes documents/dossier a soufiane/e-Motion-Vision//Vector3D.hpp:126: multiple definition of `eMV::Vector3D<float>::operator==(eMV::Vector3D<float> const&) const'
    ne\Mes documents\dossier a soufiane\e-Motion-Vision\Vector3D.hpp:126: first defined here
    ...
    Voilà mon code :
    Vector3D.h
    Vector3.hpp

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #define Type(X) typedef X<char>             c  ## X;\
                    typedef X<unsigned char>    uc ## X;\
                    typedef X<short>            s  ## X;\
                    typedef X<unsigned short>   us ## X;\
                    typedef X<int>              i  ## X;\
                    typedef X<unsigned int>     ui ## X;\
                    typedef X<long>             l  ## X;\
                    typedef X<unsigned long>    ul ## X;\
                    typedef X<size_t>           z  ## X;\
                    typedef X<float>            f  ## X;\
                    typedef X<double>           d  ## X;\
                    typedef X<long double>      ld ## X

  5. #5
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    C'est parce que ta fonction n'est pas inline alors qu'elle se trouve dans un .h

    Soit tu la met inline, soit tu la déclare seulement dans le .h et tu l'implémente dans le cpp.

    Les typedefs n'instancient pas les classes, ils ne peuvent pas être en cause.

  6. #6
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut
    Je ne peux pas la mettre dans un *.cpp puisque c'est une classe générique alors qu'inclue un fichier *.hpp. Et même en déclarant inline ou sans comme je l'es montré dans la vrai classe ça Bug Quand même.

    PS : Ne pas tenir compte de la première classe mais des liens Vector3D.h Vector3.hpp

  7. #7
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Salut, plutôt que de placer inline devant les déclarations, essaye de le placer devant les définitions des fonctions.

    Je ne suis pas sûr qu'une fonction déclarée friend inline le soit vraiment, vu qu'elle n'apartient pas à la classe.

  8. #8
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par SKone Voir le message
    Je ne peux pas la mettre dans un *.cpp puisque c'est une classe générique alors qu'inclue un fichier *.hpp.
    Les specialisations explicites completes ne sont pas des templates mais des vraies definitions. Si tu veux eviter la duplication, il faut les declarer dans les entetes et les definir une seule fois.

    Et même en déclarant inline ou sans comme je l'es montré dans la vrai classe ça Bug Quand même.
    Les specialisations ne sont pas inline.


    En passant, ton idee de specialiser la comparaison pour les instantiations sur les flottants est deja contestable. Ton implementation elle est erronee sans debat possible. J'ai deja explique comment faire et j'ai la flemme de chercher le message precis.

  9. #9
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut
    En effet ça marche tu pourrais m'expliqué pourquoi en mettant le Inline dans la définition ça marche

  10. #10
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par SKone Voir le message
    En effet ça marche tu pourrais m'expliqué pourquoi en mettant le Inline dans la définition ça marche
    Comme pour n'importe quelle definition de fonction non template.

  11. #11
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Je t'ai dit, les opérateurs déclarés friend ne sont pas membres de la classe. Il n'y a donc pas de raison que la classe puisse avoir une influence sur l'inline ou pas de l'opérateur.

    Imagine une fonction void func(); du namespace global et deux classes A et B.

    A déclare friend void func() et B déclare friend inline void func().

    Comment le compilateur décide si il faut inliner ou pas ?

    Par habitude je place le mot clef inline devant mes définitions, toujours.

  12. #12
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut
    Résolu.

    Mais en quoi faire :
    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
    template <class T>
    inline bool Vector3D<T>::operator==(const Vector3D<T> &v) const
    {
        return (x == v.x && y == v.y && z == v.z);
    }
     
    template <>
    inline bool Vector3D<float>::operator==(const Vector3D<float> &v) const
    {
        const float epsilon = std::numeric_limits<float>::epsilon();
        return (fFunc::abs(x - v.x) <= epsilon &&
                fFunc::abs(y - v.y) <= epsilon &&
                fFunc::abs(z - v.z) <= epsilon);
    }
     
    template <>
    inline bool Vector3D<double>::operator==(const Vector3D<double> &v) const
    {
        const double epsilon = std::numeric_limits<double>::epsilon();
        return (dFunc::abs(x - v.x) <= epsilon &&
                dFunc::abs(y - v.y) <= epsilon &&
                dFunc::abs(z - v.z) <= epsilon);
    }
     
    template <>
    inline bool Vector3D<long double>::operator==(const Vector3D<long double> &v) const
    {
        const long double epsilon = std::numeric_limits<long double>::epsilon();
        return (ldFunc::abs(x - v.x) <= epsilon &&
                ldFunc::abs(y - v.y) <= epsilon &&
                ldFunc::abs(z - v.z) <= epsilon);
    }
    Est faux ? Et comme les flottants engendre des erreurs en quoi c'est contestable de les spécialisées ? La seul raison est que:
    std::numeric_limits<int>::epsilon() = 0;

  13. #13
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Quelle est la definition d'epsilon? En quoi est-ce que c'est un borne pertinente?

  14. #14
    Membre éclairé

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Points : 858
    Points
    858
    Par défaut
    À noter aussi qu'un opérateur == utilisant un epsilon ne sera pas transitif.

  15. #15
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut
    Si je prends 2*epsilon ça pourrait marché ? Enfin c'est du bricolage mais ça peut marché... Et la transitivité sera respecté ?

  16. #16
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Ben... non, l'écart sera juste plus grand. Il restera des cas où a==b et b==c mais a!=c

  17. #17
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut
    Donc quel méthode propose tu pour faire face à ce genre de problème. => Au problème engendré par les erreurs dû au flottant... ?

  18. #18
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Tout dépend du domaine d'utilisation.

    Si tu travaille sur un projet de jeu video qui ne demande pas une grande précision dans les calculs, tu pourras te permettre des erreurs sur les flottants sans que ce soit visible à l'oeil du joueur.

    Si tu fais une appli pour la Nasa, je doute que tu utilises la même représentation des nombres flottants.

    Tu ne peux pas trouver une seule solution générique pour ce probleme qui satisfasse tout les utilisateurs de ta bibli.

  19. #19
    Membre actif Avatar de SKone
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2004
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2004
    Messages : 333
    Points : 250
    Points
    250
    Par défaut
    Je fais un moteur Physique qui n'as pas pour but le temps réel donc je demande une grande précision mais pour l'instant je n'est pas encore codé ma classe pour les nombres flottants très précis. Si la fonction epsilon est là dans le standard c'est bien que le nombre retourné est l'epsilon que je cherche ?

  20. #20
    Membre éclairé Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Points : 871
    Points
    871
    Par défaut
    Citation Envoyé par SKone Voir le message
    Je fais un moteur Physique qui n'as pas pour but le temps réel donc je demande une grande précision mais pour l'instant je n'est pas encore codé ma classe pour les nombres flottants très précis. Si la fonction epsilon est là dans le standard c'est bien que le nombre retourné est l'epsilon que je cherche ?
    Cet epsilon est le plus petit flottant non nul tel que 1.0 + epsilon != 1.0 en fait.

    Il faudrait ajuster cet epsilon avec les valeurs considérées, pour être plus juste.

    Mais là encore, c'est plus ou moins valable selon les applications, et sûrement suffisant pour les jeux vidéos.

Discussions similaires

  1. Problème de multiple définition
    Par Tallon159 dans le forum C++
    Réponses: 10
    Dernier message: 16/01/2013, 02h04
  2. comment résoudre un problème de multiple définition
    Par razily dans le forum Débuter
    Réponses: 8
    Dernier message: 24/03/2010, 19h29
  3. problème avec une classe générique
    Par bard123 dans le forum Langage
    Réponses: 4
    Dernier message: 27/06/2008, 11h09
  4. probléme lors de définition d'une classe
    Par s-ehtp dans le forum C++
    Réponses: 2
    Dernier message: 05/03/2008, 09h58
  5. Problème avec une classe générique
    Par Core8 dans le forum C++
    Réponses: 3
    Dernier message: 19/03/2007, 03h18

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