Journal Problèmes de compilation g++ (suite)

Posté par .
Tags : aucun
2
8
mar.
2004
Bonsoir à tous les journautes ...

Voila, pour ceux qui avaient eu la bonté de suivre le précédent journal ( http://linuxfr.org/~Obsidian/9726.html(...) ), ou j'exposais
mes problèmes d'utilisation des opérateurs ...

D'abord, gcc doc roulaize, si certains les cherchent.

http://gcc.gnu.org/onlinedocs/(...)
http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Option-Index.html#Optio(...)

et aussi:

" http://es-sun2.fernuni-hagen.de/cgi-bin/info2html?(gcc(...))Option%20Index "

Et surtout, j'ai identifié le problème mais ne sait pas comment le résoudre.

class A
{
public:
A & operator << (unsigned long int);
operator bool ();
}


int main (void)
{
A << 4;
return 0;
}

Petite explication:
- Je dérive l'opérateur « << » pour m'en servir à des fins de décalage.
- Je dérive l'opérateur bool car mon objet peut avoir un statut défini ou indéfini qui doit transparaitre lorsqu'il est impliqué dans une condition.

Et c'est çà qui provoque l'ambigüité. g++ considère non seulement que dans mon main, le « << » est en fait la fonction membre .operator<<(ulong) (normal), mais également qu'il pourrait caster ma classe en booléen, donc en entier, et donc utiliser l'opérateur normal.

Cela me pose problème parce que cela limite énormément les le champs d'action efficace de la surcharge des opérateurs. Que le compilo se plaigne lorsqu'il y a des ambigüités à un même niveau (deux méthodes d'une même classe, par exemple), je le conçois, mais là, le cheminement à faire est bien trop long pour que cela soit vraiment ambigü, et mon cas de figure est légitime ...

Voila, si quelqu'un trouve l'option magique ...
  • # Re: Problèmes de compilation g++ (suite)

    Posté par (page perso) . Évalué à 1.

    Une (très grosse) bidouille mais qui semble marcher :
    class A
    {
    public:
    
            template <class T>
            A operator<<(const T x) const
            {
                    // ...
            }
    
            operator bool() const
            {
                    // ...
             }
    };                                                                                            
    
    Pas mieux pour l'instant...
  • # Re: Problèmes de compilation g++ (suite)

    Posté par . Évalué à 1.

    Je trouve le comportement de g++ rationnel.

    A << 4

    renvoie une lvalue de type 'A' et g++ finalement caste l'ensemble vers un bool (c'est normal ça par contre ?).

    Le bon code ne serait-il pas:

    A <<= 4

    pour ne pas avoir l'effet de bord ?
    • [^] # Re: Problèmes de compilation g++ (suite)

      Posté par (page perso) . Évalué à 1.

      A << 4

      renvoie une lvalue de type 'A' et g++ finalement caste l'ensemble
      vers un bool (c'est normal ça par contre ?).


      Non, justement. Il fait d'abord une conversion implicite de A vers bool, applique l'opérateur <<, et renvoie un bool.
      Et c'est bien là le problème.
      • [^] # Re: Problèmes de compilation g++ (suite)

        Posté par . Évalué à 1.

        J'ai jeté un coup d'oeil dans un bouquin de C++.
        Tu ne surcharges pas l'opérateur ! je sais pas pourquoi g++ ne bronche pas :(
        La signature pour surcharger l'opérateur '<<' est:

        A & operator<<(int) const;

        donc A << 4 ne modifie pas A.

        Il faut donc faire A <<= 4 et surcharger cet opérateur:

        A & operator<<=(int);

        pour faire ce que tu désires.
        • [^] # Re: Problèmes de compilation g++ (suite)

          Posté par . Évalué à 1.

          Oups ! Bien vu, mais en fait c'est effectivement le cas. La classe présentée est en fait un exemple simplifiée que j'ai écrit de tête. Donc je cherche encore...
      • [^] # Re: Problèmes de compilation g++ (suite)

        Posté par (page perso) . Évalué à 1.

        Mon gcc 3.3 me dit que

        ISO C++ says that `A& A::operator<<(long int)' and `operator<<' are ambiguous even though the worst conversion for the former is better than the worst conversion for the latter

        Par exemple avec <<(int) ça compile, de même si on écrit :

        A a;
        a << 4L;
  • # Re: Problèmes de compilation g++ (suite)

    Posté par (page perso) . Évalué à 0.

    La surcharge des opérateurs, ça sert rien qu'à rendre le code illisible en changeant les comportement par défaut qu'on attend de nos signes. Et il n'y a qu'à voir vos exemples pour en plus être persuadé que c'est imbitable à utiliser.

    Heureusement que les ingénieurs de Sun qui ont conçu le Java ont bien compris ça.


    (flute, je perds mes poils)
    • [^] # Re: Problèmes de compilation g++ (suite)

      Posté par . Évalué à 1.

      Troll détecté (ok, il n'était pas bien planqué).

      C'est une question de point de vue, évidement. Pour ma part, j'aime le C++ parce qu'il me permet justement de faire ces choses là, et je trouve que c'est nécessaire lorsque l'on veut réellement définir de nouveaux types. Sinon ce ne sont que des fonctions et des structures, avec règles de nommage locales. Et en ce qui concerne les opérateurs, le problème vient du fait que beaucoup de gens travestissent l'usage initial des opérateurs, souvent à tort et à travers. Dans mon cas, « << » sert réellement à décaler mon objet vers la gauche.

      Exemple, la concaténation des chaines en Java avec l'opérateur "+". Ce serait sympa de pouvoir exprimer un objet de la même façon sans avoir à systématiquement passer par un .getString(). Autre exemple - ambassadeur du développement C++ - : les nombres complexes. C'est typiquement un objet qui doit se comporter comme un réel lorsque sa partie imaginaire est nulle, et qui se mélange aux équations traditionnelles. C'est impossible à faire proprement en Java, dans lequel on se mélange déjà les pattes entre opérateur = et méthodes .equal() à cause des références, sans entrer dans un cas de figure comme le nôtre. Bref, le Java oriente très judicieusement le problème de façon à favoriser les cas de figures les plus courants, mais en aucun le résoud.

      Le Java est un très bon langage en soi, et pour l'usage pour lequel il a été conçu (portabilité + rapidité de développement), mais bon nombre de facette du développement objet ont été volontairement éllipsés (surcharge des opérateurs, héritage multiple, template ...). L'effet pervers vient du fait que beaucoup de gens, aujourd'hui s'orientent Java parce que toutes les difficultés sont officiellement masquées par le standard. « L'héritage multiple finirait par poser trop de problème, spécialement si toutes les classes dérivent de Object. Pas de problème, on n'a qu'a interdire l'héritage multiple ! ». Soit, mais tôt ou tard, le travail devra être fait quand même, et inexorablement, on finira par rencontrer un problème équivalent.
      • [^] # Re: Problèmes de compilation g++ (suite)

        Posté par . Évalué à 0.

        > ...le problème vient du fait que beaucoup de gens travestissent l'usage initial des opérateurs, [...]. Dans mon cas, « << » sert réellement à décaler mon objet vers la gauche

        C'est quoi "l'usage initial" de l'opérateur "<<" ?
        Car dire que c'est "décaler un objet vers la gauche" n'est pas super précis et ne peut etre une spécification.
        De plus regarde "cout" et "cin", on ne peut pas dire aussi simplement que l'on décale la "sortie" vers la gauche ou "l'entrée" vers la droite (a part en approximant d'un facon plus que douteuse ...).
        Il y à eu un long thread sur la mailling list de SmallEiffel sur la surcharge d'oppérateur pour info ...

        Mon avis perso: La surcharge d'opérateur ca à l'air super mais il faut voir un peu plus loin ... Si a chaque signe "+" ou "<<" je doit recomprendre ce qu'a fait le concepteur, ca va etres ingérable. Garder cette surcharge à un nombre limité de cas et au plus courant me semble le meilleur copromis (String est dans ce cas).

        > Le Java [...], mais bon nombre de facette du développement objet ont été volontairement éllipsés ...
        au passage: s/éllipsés/eclipsés ... et sans jeux de mots ;)

        > surcharge des opérateurs ...
        C'est discutable, la surcharge existe pour le type le plus "lourd" (String). Ajouter ce comportement pour une infime partie des besoins réel n'était peut-etres pas leur objetifs premier ...
        (au passage, la surcharge d'opérateur n'est pas un facette du "développement objet")

        >...héritage multiple ...
        La il y a aussi des problèmes "techniques": Ajouter l'héritage multiple aurrait obligé d'ajouter un mécanisme pour solutionner les problèmes qu'il apporte (à moins de ne riens faire comme en C++, mais bon a partir d'un moment fau etres sérieux ...), du coup le tout aurrait peut-etres était un peu lourd pour un langage ce voulant simple ...
        Ensuite l'implémentation de l'héritage multiple est un peu plus couteuse en termes de ressources
        donc il ont dut effectuer un choix ...

        > ...template ...
        La c'est clair qu'ils ce sont méchament gofré les gars ...
        (au passage, la généricitée n'est pas un facette du "développement objet")
        • [^] # Re: Problèmes de compilation g++ (suite)

          Posté par . Évalué à 1.

          l'héritage multiple pose aussi de gros problème lors de la réutilisation de classe en format byte code. De toutes façon, l'héritage multiple est le plus souvent utiliser comme interface donc bon...

          "La première sécurité est la liberté"

        • [^] # Re: Problèmes de compilation g++ (suite)

          Posté par . Évalué à 1.

          au passage: s/ellipsés/eclipsés ... et sans jeux de mots ;)

          Une ellipse, quand ce n'est pas un « cercle applati », c'est une figure linguistique qui permet d'omettre des éléments d'une phrase ou d'un discours, sans en changer le sens. C'est également le terme que l'on emploie pour parler des mots « tronqués »: metro(politain), stylo(graphe), etc.
  • # Re: Problèmes de compilation g++ (suite)

    Posté par . Évalué à 1.

    > A & operator << (unsigned long int);

    En C++ il n'y a pas de propotion automatique comme en C lors des appels de fonction. En C un float est converti en double et un int en long.

    Donc il faut convertir ton 4 (qui est un int) en un unsigned long avec (par exemple) :
    a << (unsigned long) 4 ;

    Un bool étant un int, il y a ambiguité.

    Enfin c'est les vagues souvenirs que j'ai du C++ (ça fait depuis longtemps que j'en est plus fait).
    • [^] # Re: Problèmes de compilation g++ (suite)

      Posté par . Évalué à 1.

      C'est vrai mais ce qui me chagrine, c'est que cela fonctionnait très bien avec gcc/g++ 2.95 ... De plus dans mon esprit, étant donné l'expression

      A << 4

      Il me semblait que puisque A est une lvalue immédiatement suivie par un opérateur, le compilo devrait considérer que celui-ci est une fonction membre de l'objet: A.operator << (4). Effectivement, le typage semblant être renforcé dans la version 3.2, un "4" tout seul n'est peut-être pas plus proche d'un long que d'un bool, mais tout de même ce casting à gauche me rends perplexe.

      Le problème, c'est que cette classe fait en fait partie d'une bibliothèque qui doit donc compiler partout, et qu'en plus je ne dispose pas de 2.95 sur toutes les plateformes sur lesquelles je travaille. Pour achever le tout, j'ai connu quelques difficultés au runtime avec cette version: parfois les exceptions n'étaient pas remonté (Abort direct).
      • [^] # Re: Problèmes de compilation g++ (suite)

        Posté par . Évalué à 2.

        > cela fonctionnait très bien avec gcc/g++ 2.95

        g++ 2.95 est tres loin d'etre une reference pour le C++. Attention !

        Je developpe actuellement sur solaris avec le compilo CC de sun ( qui a la reputation d'assez bien respecter le standard) . j'ai porté le code sur une linux Mdk 9.2 qui a un g++ 3.02 . c'est ok sans pb. Mais je viens d'essayer de porter sur une debian woody avec g++ 2.95 , et j'ai plein d'emmerdes diverses.
      • [^] # Re: Problèmes de compilation g++ (suite)

        Posté par . Évalué à 2.

        > mais tout de même ce casting à gauche me rends perplexe.

        Ben fais une surcharge pour tout les types que tu peux utiliser :
        - char, short, int, long, long

        C'est bourrin et c'est généralement cher. C'est a utiliser pour quelques librairies très générales.

        Ou appuis toi sur le compilo pour que tout le monde utilise des "unsigned long".

        Ton opérateur attend un "unsigned long". Je ne pense pas que lui donner un int soit particuliairement rigoureur... surtout si c'est une valeur négative (le MSB est décalé, etc... une horreur).
  • # Re: Problèmes de compilation g++ (suite)

    Posté par . Évalué à 2.

    Le compilo a le choix entre 2 cast possibles, et ne peut pas décider seul. On pourrait surcharger l'opérateur encore une fois qui s'occuperait de caster "proprement".

    En gros dans ton exemple on ajouterait quelque chose du genre :
    A & operator << (int B) { return this << (unsigned long int) B;}

    C'est surement faux syntaxiquement et c'est pas testé, mais c'est juste pour donner l'idée et a priori ça lève l'ambiguité, vu qu'il trouve une méthode dont la signature correspond parfaitement (sans étape de cast implicite). Il suffit alors de surcharger tous les cas envisageables (c'est bourrin, d'ou l'interet du template dans le premier commentaire).
    L'ambiguité ne vient pas de ta lib, mais d'un conflit à l'utilisation avec une autre lib, dans ce cas la lib standard. Si tu veux être sûr du sucre syntaxique que tu proposes à l'utilisateur, je pense qu'il vaut mieux gérer tous les cas dans ta lib et faire du code déterministe plutôt que de te reposer sur les mécanismes de sucre syntaxique proposés par le compilo (cast implicite par exemple).
    • [^] # Re: Problèmes de compilation g++ (suite)

      Posté par . Évalué à 1.

      Je crois que c'est effectivement la meilleure solution.
      Je prends effectivement en charge un certain nombre de situations comme celles-ci, mais je ne pensais pas qu'un casting à gauche provoquerait cette ambigüité.

      Merci à tous pour vous être penchés sur le problème. J'essaie et vous tiens au courant !

Suivre le flux des commentaires

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