Forum Programmation.c++ Ambigüités entre opérateurs

Posté par  .
Étiquettes : aucune
0
7
déc.
2004
Bonsoir à tous.

Bon, mon problème est probablement classique mais j'ai beaucoup de mal à trouver de l'aide sur ce point précis. La situation est la suivante :

J'ai défini une classe qui fait à peu près le même boulot que BigInt en Java, à savoir gérer un entier sans limite de taille en mémoire (il grossit ou réadapte sa taille tout seul), plus autres features locales. Evidemment, c'est une classe qui est très proche, au yeux de l'utilisateur, des types entiers natifs au compilateur tels que int, long, short, et consors. Il doit donc être utilisable de la même façon. Et bien sûr, on doit pouvoir l'initialiser aussi simplement que le reste :

BigInt x;
x = 10;

Pour ce faire, j'ai défini un constructeur de BigInt pour chaque type d'entier natif (et un constructeur de copie). Par la suite, tous les autres opérateurs reçoivent exclusivement le type BigInt en argument. C'est très bien comme cela, puisque chaque fois que je rencontre un ...

x + 10

... par exemple, l'opérande est convertie dans le type de l'objet, et on travaille au même niveau.




La classe est désormais pleinement fonctionnelle, sauf que j'ai besoin de pouvoir reconvertir l'objet en types natifs et là, le bas blesse parce que je suis obligé de redéfinir les opérateurs de transtypages. C'est pas un problème en soi, mais si je fais par exemple :

x < 10

... j'obtiens :

ambigous overload for 'BigInt& < int' operator
candidates are:
operator<(long long unsigned int,int) <built-in>
operator<(long long int,int) <built-in>
operator<(long int,int) <built-in>
...


Le problème étant que dans le cas de "<", le compilateur ne l'utilise pas comme une "méthode" de BigInt (l'opérateur surchargé) mais essaie au préalable de convertir l'opérande de gauche (mon objet x) en utilisant les opérateurs de transtypage, pour utiliser l'opérateur externe et built-in qu'il connaît.

Y a-t-il moyen de demander au compilo de ne pas faire tant de zèle ? De respecter le type de la valeur de gauche ? Autrement je vais être obligé d'utiliser des méthodes style GetInt(), GetLong(), etc. pour obtenir les valeurs natives, et franchement l'objet deviendra inutilisable.

Merci d'avance pour votre aide.

PS: g++ v3.2.2 sur une RedHat 9.
  • # diversion

    Posté par  (site web personnel) . Évalué à 3.

    t'as essayer avec une methode externe ?
    Operator < (BigInt &, truc &)
    et tu la rajoute en friend dans ta classe.
    (et non Friend ne brise pas l'encapsulation, voir a ce sujet les commentaires de B. Stroustup : http://www.research.att.com/~bs/homepage.html(...) )
  • # Re : Ambigüités entre opérateurs

    Posté par  . Évalué à 2.

    Pour ce faire, j'ai défini un constructeur de BigInt pour chaque type d'entier natif

    Pourquoi pour chaque type ? Vu que les types entiers peuvent être promus entre eux, un constructeur prenant un int en paramètre suffit largement.

    La classe est désormais pleinement fonctionnelle, sauf que j'ai besoin de pouvoir reconvertir l'objet en types natifs

    Et si la valeur du BigInt est plus grande que celle du type natif que tu veux, il se passe quoi ?

    Ce que je ferais, c'est de mettre des fonctions style GetLong, et un opérateur < pour comparer deux BigInt, la comparaison entier->BigInt étant gérée par le constructeur.
    • [^] # Re: Re : Ambigüités entre opérateurs

      Posté par  . Évalué à 2.

      Merci pour ces réponses

      Pourquoi pour chaque type ? Vu que les types entiers peuvent être promus entre eux, un constructeur prenant un int en paramètre suffit largement.

      C'est vrai. Mais au moment où j'avais commencé la classe en question, je ne savais pas si le compilateur aurait la bonne idée de le faire. J'aurais pu vérifier, toutefois ...

      Et si la valeur du BigInt est plus grande que celle du type natif que tu veux, il se passe quoi ?

      Typiquement, j'adopte le même comportement que lorsque l'on passe d'un long à un short, par exemple. Je tronque et conserve les octets de poids faible. C'est aussi pour cela que je veux qu'un entier soit implicitement converti vers un BigInt et pas l'inverse, autrement les résultats seront erronés.

      Ce que je ferais, c'est de mettre des fonctions style GetLong, et un opérateur < pour comparer deux BigInt, la comparaison entier->BigInt étant gérée par le constructeur.

      C'est que je voulais éviter. L'opérateur s'appuyant sur les constructeurs est déjà en place, mais l'utilisateur ne comprendra pas pourquoi dans un sens on peut directement comparer un BigInt à un entier, et pas dans l'autre ...
      • [^] # Re: Re : Ambigüités entre opérateurs

        Posté par  . Évalué à 2.

        C'est aussi pour cela que je veux qu'un entier soit implicitement converti vers un BigInt et pas l'inverse, autrement les résultats seront erronés.


        Donc pas d'opérateur de conversion :-)

        C'est que je voulais éviter. L'opérateur s'appuyant sur les constructeurs est déjà en place, mais l'utilisateur ne comprendra pas pourquoi dans un sens on peut directement comparer un BigInt à un entier, et pas dans l'autre ...


        Dans ce cas, tu fait comme distait Pooly au début du thread (http://linuxfr.org/comments/506759.html#506759(...) ) et tu remplaces ta fonction membre pour l'opérateur < par une fonction non membre, qui est amie de la classe BigInt.
      • [^] # Re: Re : Ambigüités entre opérateurs

        Posté par  . Évalué à 1.


        C'est que je voulais éviter. L'opérateur s'appuyant sur les constructeurs est déjà en place, mais l'utilisateur ne comprendra pas pourquoi dans un sens on peut directement comparer un BigInt à un entier, et pas dans l'autre ...


        Et une méthode compare() qui accepterai tout les types natifs ?
        Ca eviterai aussi tous les pbs de conversion en te permettant de convertir toi même tes entiers en BigInt.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.