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 :

Gérer les conversions intempestives


Sujet :

C++

  1. #1
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut Gérer les conversions intempestives
    Salut à vous !

    J'explique mon problème :
    Je travaille en ce moment à créer des classes alternatives pour les types de donnée de base (int, float, ...).
    Le soucis c'est que je n'arrive pas à dompter le compilo...
    Exemple, si j'écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    s_uint i = 15u;
    s_float f = i/10.0f;
    ... hé bien le compilateur me dis qu'il y a "ambigous overload" entre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    s_uint s_uint::operator/ (s_uint)
     
    et
     
    s_float s_uint::operator/ (s_float)
    Les seuls constructeurs qui peuvent servir dans ce cas sont :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    s_uint(unsigned int uiValue);
    s_uint(s_float fValue);
     
    et
     
    s_float(float fValue);
    s_float(s_uint uiValue);
    Le compilateur à donc deux options :
    10.0f -> s_float(10.0f) -> operator/ (s_float)
    10u -> s_uint(10u) -> operator/ (s_uint)
    Mon 10.0f se trouve miraculeusement transformé en entier. Y a-t-il un moyen d'empêcher ça ? Je peux comprendre qu'un entier puisse être transformé en float automatiquement, mais là...



    Autre soucis :
    J'ai créé une classe dans le même style pour gérer les chaines de caractères (basée sur std::string), et j'ai des erreurs de compilation que je n'avais pas avec std::string :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    s_str s1 = "ça";
    s_str s2 = "salut " + s1 + " va ?";
    ... me donne :
    error: no match for 'operator+' in '"salut " + s1'
    J'imagine qu'il cherche un "operator+ (s_str)" pour const char*, ce qui biensûr n'existe pas. Or, avec std::string : pas de problème. Comment font-ils ?


    Merci d'avance pour vos réponses !

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Kalith Voir le message
    Je travaille en ce moment à créer des classes alternatives pour les types de donnée de base (int, float, ...).
    C'est quoi le but ?
    Citation Envoyé par Kalith Voir le message
    Les seuls constructeurs qui peuvent servir dans ce cas sont :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    s_uint(unsigned int uiValue);
    s_uint(s_float fValue);
    Le second devrait être déclaré explicit.
    Citation Envoyé par Kalith Voir le message
    J'imagine qu'il cherche un "operator+ (s_str)" pour const char*, ce qui biensûr n'existe pas. Or, avec std::string : pas de problème. Comment font-ils ?
    Il cherche aussi une fonction libre (pas membre de classe) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    s_str operator+(char const *, s_str const &);
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Merci beaucoup
    Je testerais ça plus tard et j'éditerai ce message.

    Le but c'est d'avoir plus de fonctionnalités (du style nombre infini, NaN), et de pouvoir écrire :
    ... au lieu de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SaturateFloat(myFloat);
    L'autre avantage c'est que je peux donner plus d'information en retour d'une fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    s_float Toto()
    {
        if (bien)
        {
            return 5.0f;
        }
        else
        {
            return s_float(s_float::FLOAT_NAN);
        }
    }
    Ensuite je peux tester la validité du s_float retourné, et je sais alors si tout s'est bien passé.
    Biensûr, c'est réalisable autrement (à la DirectX) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    bool Toto(float& f)
    {
        if (bien)
        {
            f = 5.0f
            return true;
        }
        else
        {
            return false;
        }
    }
    Mais je trouve ça plus lourd et moins pratique à utiliser.

    Et puis ça me fait un bon exercice sur les opérateurs, j'avais jamais eu l'occasion d'en écrire beaucoup (j'ai aussi appris des trucs au sujet de const, comme quoi).

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Tu sais que les floats gèrent nativement la notion de NAN, ainsi que d'autres valeurs spéciales (+/-INF) si ton compilateur répond à la norme IEE 745 (ce qui est la cas de tous les compilos courants) ?

    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Ah, ben non je sais pas
    Comment on fait pour attribuer la valeur NaN à un float dans ce cas ?
    J'ai trouvé la fonction isnan() mais pas l'autre.

    Mais ça ne fonctionne que pour les float/double d'après ce que j'ai lu. Donc j'ai pas fait tout ça pour rien

    L'autre petit atout c'est que j'ai défini operator! différemment de d'habitude : au lieu de tester si la valeur vaut 0 (quasiment inutile la plupart du temps), il teste si le nombre est valide (ni NaN, ni infini).
    Le soucis c'est que si je défini operator bool() pour pouvoir faire un truc du style :
    ... ça met le foutoir dans les opérations. Du coup si j'écris :
    ... il me dit qu'il y a ambigous overload entre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    operator+(int, int)
     
    et
     
    s_int s_int::operator+(s_int) const
    Faudrait que je mette s_int(int) en explicit également ? Du coup ça va court-circuiter la manip pour mélanger les int et les floats

    Comme ça m'a soulé, je l'ai supprimé et j'ai mis une fonction IsValid() qui joue le même rôle. C'est moins classe, mais au moins je suis sûr du résultat.

  6. #6
    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 Kalith Voir le message
    Le soucis c'est que si je défini operator bool() pour pouvoir faire un truc du style
    On ne peut pas dire que j'aime beaucoup ce genre d'idees. Les conversions implicites se marient tres mal avec les surcharges et on controle beaucoup mieux l'effet des surcharges que des conversions implicites.

    La technique habituelle est de definir un operateur vers un type qui puisse etre utilise dans un if mais dans aucun autre contexte de maniere involontaire, on utilise souvent un pointeur vers fonction membre (voir l'implementation des smart pointeurs, on doit l'y trouver).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  7. #7
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    On ne peut pas dire que j'aime beaucoup ce genre d'idees. Les conversions implicites se marient tres mal avec les surcharges et on controle beaucoup mieux l'effet des surcharges que des conversions implicites.
    Tout à fait d'accord. J'ai testé, et détesté ^^

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    La technique habituelle est de definir un operateur vers un type qui puisse etre utilise dans un if mais dans aucun autre contexte de maniere involontaire, on utilise souvent un pointeur vers fonction membre (voir l'implementation des smart pointeurs, on doit l'y trouver).
    J'ai regardé les smart pointers de boost mais j'ai pas tout saisi.
    Est-ce qu'on peut plus simplement déclarer un opérateur vers void*, retourner NULL si ça va pas et 1 si tout va bien ?

    Edit : non, ça embrouille les opérations également. Même si j'utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typedef s_int TmpFuncPtr();
    operator TmpFuncPtr*() const;
    J'ai dû mal saisir le concept

    Edit 2 : ok c'est bon, j'avais pas la bonne synthaxe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typedef  s_int (s_int::*TmpFuncPtr)();
    operator TmpFuncPtr() const;
    Par contre, j'ai testé le coup du explicit, mais ça ne marche pas : l'erreur persiste.

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Kalith Voir le message
    Le soucis c'est que si je défini operator bool() pour pouvoir faire un truc du style :
    Dans le futur, on pourra écrire pour gérer ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    explicit operator bool()
    En attendant, comme l'a dit Jean-Marc, il faut ruser. La page http://www.artima.com/cppsource/safebool.html détaille ça.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Membre éclairé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Points : 764
    Points
    764
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Dans le futur, on pourra écrire pour gérer ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    explicit operator bool()
    En attendant, comme l'a dit Jean-Marc, il faut ruser. La page http://www.artima.com/cppsource/safebool.html détaille ça.
    Pas mal le coup du if (!!value)
    Comme écrit dans mon message précèdent, j'ai utilisé la technique de Jean-Marc, et le petit soucis c'est que maintenant :
    ... me donne ambigous overload :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    operator!=(void (Frost::s_uint::*)(), void (Frost::s_uint::*)())
     
    et
     
    bool Frost::s_uint::operator!=(Frost::s_uint) const
    Ca n'arrive que si je compare avec 0.
    Heureusement j'ai une méthode IsNull() que je peux utiliser à la place, mais bon...

    Edit : ...et j'en profite pour répéter que mettre le constructeur en explicit ne résout pas le problème d'ambigüité de mon premier post.

Discussions similaires

  1. [D5][SQL Server] Conserver des images dans la BDD
    Par FONKOU dans le forum Bases de données
    Réponses: 8
    Dernier message: 08/06/2008, 19h58
  2. [Frame] Gérer les composants
    Par chastel dans le forum Débuter
    Réponses: 4
    Dernier message: 07/05/2004, 17h57
  3. Gérer les clics sur les boutons
    Par cyberlewis dans le forum Windows
    Réponses: 4
    Dernier message: 08/02/2004, 15h34
  4. Comment gérer les espaces blancs?
    Par Lambo dans le forum XML/XSL et SOAP
    Réponses: 10
    Dernier message: 16/05/2003, 09h44
  5. gérer les jpg dans une fenetre directdraw???
    Par Anonymous dans le forum DirectX
    Réponses: 1
    Dernier message: 14/06/2002, 13h39

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