• # l'article est intĂ©ressants

    Posté par  . Évalué à 4.

    mais les commentaires au moment ou je le lis sont affligeant. Outre ceux qui disent que c'est une mauvaise idée sans dire pourquoi, d'autre qui disent qu'il faudrait plutÎt passer a Rust sans expliquer pourquoi l'analyse de l'auteur n'est pas bonne


    ou celui qui n'a pas l'air d'avoir remarque que depuis Windows ME, la qualitĂ© de FenĂȘtre s'est grandement amĂ©lioré 

    Bon je je vais pas tergiverser, je sais bien pourquoi je suis ici :D

    Le point clĂ© est soulignĂ© par l'auteur, il faut se contenter d'un sous ensemble de c++, chose qui a l'air d'avoir Ă©tĂ© Ă©ludĂ© par les commentateur dev C++ professionnels. Je trouve personnellement que le c++ ajoute des fonctionnalitĂ© manquante au C, comme les destructeurs; ou les templates qui offrent une bonne sĂ©curitĂ© et de bonne capacitĂ© de spĂ©cialisation en fonction des types; pour faire la mĂȘme chose avec des macros, faut relire 10 fois avant de s'assurer qu'on a bien fait taff.

    L'autre Ă©norme avantage de c++ c'est que la base de code principale peu dans son immense majoritĂ© ĂȘtre reprise telle quelle. Par contre
 bonjour les tests de non rĂ©gression


    Il ne faut pas décorner les boeufs avant d'avoir semé le vent

    • [^] # Re: l'article est intĂ©ressants

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

      les templates qui offrent une bonne sĂ©curitĂ© et de bonne capacitĂ© de spĂ©cialisation en fonction des types; pour faire la mĂȘme chose avec des macros, faut relire 10 fois avant de s'assurer qu'on a bien fait taff.

      #define cmp(a, b) _Generic(b, int : cmpInt, float: cmpFloat, default: cmpPtr)(a,b)
      

      Tu te relis beaucoup de fois pour un truck qui se fait en une ligne de code, et est assez explicite, je trouve.

      Bon ok, c'est du C11, et si tu veux faire la mĂȘme chose avec des macros en C++, ça va peu ĂȘtre plus compliquĂ©.

      • [^] # Re: l'article est intĂ©ressants

        Posté par  . Évalué à 4.

        Tu te relis beaucoup de fois pour un truck qui se fait en une ligne de code, et est assez explicite, je trouve.

        que fait cmp(1.2f, 2) et cmp(2, 1.2f); on appel pas la mĂȘme comparaison. mĂȘme question si je met des doubles, on passe dans la comparaison de pointeur, si je met des short aussi, en c++ y'a une belle erreur de compilation qui dit qu'il y'a trop de candidats.

        j’ajouterais que 1.0 c'est double donc cmp (2.0, 1.0) appel la comparaison de pointeur

        si tu veux faire la mĂȘme chose avec des macros en C++, ça va peu ĂȘtre plus compliquĂ©.

        en c++ on va préférer les templates et/ou surcharge

        disons que la macros devient inutile, seul le template reste et tu peux lui ajouter une contrainte sur le type; tu peux faire une version full template en spécialisant plutÎt que faire la surcharge (l'un des soucis du c++ et les 15 façons de faire); bonus avec la version full template tu peux forcer celle que tu veux appeler cmp(a,b)

        au final si tu veux rester homogĂšne :

        template <typename T>
        int cmp(T a, T b) {
          static_assert(std::is_pointer<T>::value, "les paramĂštres ne sont pas des pointeurs");
          std::cout <<" ptr " ;
          return a-b;
        }
        
        template <> int cmp(int a, int b) { 
          std::cout <<" int " ;
          return a-b;
        }
        
        template <> int cmp(float a, float b) {
          std::cout <<" float " ;
          return (int)(a-b);
        }
        
        template <> int cmp(double a, double b) {
          std::cout <<" double " ;
          return (int)(a-b);
        }
        
        int main() {
          short a=1, b=2;
          std::cout << cmp(1,2) << std::endl;
          std::cout << cmp<int>(1,2.0) << std::endl;
          std::cout << cmp<double>(1.0,2) << std::endl;
          std::cout << cmp(1.0f,2.0f) << std::endl;
          std::cout << cmp(a,b) << std::endl;
        
          return 0;
        }

        bon c'est vite fait et manque les long long et un paquet d'autre types; il vaut mieux utiliser les std::is_floating_point ou std::is_integral; tu peux regretter que c'est plus long que ton oneliner, mais en fait mĂȘme pas vu qu'il faut que tu dĂ©finisse quand mĂȘme tes cmpInt, cmpFloat et cmpPtr, et on ajoute de la souplesse Ă  l'utilisation, et on peut mĂȘme l'Ă©tendre au besoin en rajoutant un type. A noter qu'on a une erreur de compilation sur cmp(a,b) car short != int, donc on passe dans le cas par dĂ©faut.

        L'erreur est explicite :

        file.cpp: In instantiation of ‘int cmp(T, T) [with T = short int]’:
        file.cpp:31:23:   required from here
        file.cpp:5:37: error: static assertion failed: les paramĂštres ne sont pas des pointeurs
            5 |   static_assert(std::is_pointer<T>::value, "les paramĂštres ne sont pas des pointeurs");
        
         In instantiation of ‘int cmp(T, T) [with T = short int]’:
        
        

        Bref je ne sais pas si ça suffit a convaincre, mais je trouve la version macro vachement plus risquée.

        Il ne faut pas décorner les boeufs avant d'avoir semé le vent

        • [^] # Re: l'article est intĂ©ressants

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

          En C, t'a une erreur aussi (Vu que 1.0 est un double, il va dans le type default, donc cmpPtr)

              #include <stdio.h>
          
              #define cmp(a, b) _Generic(b, int : cmpInt, float: cmpFloat, default: cmpPtr)(a,b)
          
              int cmpPtr(void *a, void*b) {return a == b;}
              int cmpInt(int a, int b) {return a == b;}
              int cmpFloat(float a, float b) {return a == b;}
              int main()
              {
                  printf("Hello, World! %d\n", cmp(1,1.0));
              }
          Main.c: In function ‘main’:
          Main.c:10:38: warning: passing argument 1 of ‘cmpPtr’ makes pointer from integer without a cast [-Wint-conversion]
             10 |     printf("Hello, World! %d\n", cmp(1,1.0));
                |                                      ^
                |                                      |
                |                                      int
          Main.c:3:79: note: in definition of macro ‘cmp’
              3 | #define cmp(a, b) _Generic(b, int : cmpInt, float: cmpFloat, default: cmpPtr)(a,b)
                |                                                                               ^
          Main.c:5:18: note: expected ‘void *’ but argument is of type ‘int’
              5 | int cmpPtr(void *a, void*b) {return a == b;}
                |            ~~~~~~^
          Main.c:10:40: error: incompatible type for argument 2 of ‘cmpPtr’
             10 |     printf("Hello, World! %d\n", cmp(1,1.0));
                |                                        ^~~
                |                                        |
                |                                        double
          Main.c:3:81: note: in definition of macro ‘cmp’
              3 | #define cmp(a, b) _Generic(b, int : cmpInt, float: cmpFloat, default: cmpPtr)(a,b)
                |                                                                                 ^
          Main.c:5:26: note: expected ‘void *’ but argument is of type ‘double’
              5 | int cmpPtr(void *a, void*b) {return a == b;}
                |                     ~~~~~^
          
          

          Si tu enlÚves le default t'a aussi une erreur :

          Main.c: In function ‘main’:
          Main.c:10:40: error: ‘_Generic’ selector of type ‘double’ is not compatible with any association
             10 |     printf("Hello, World! %d\n", cmp(1,1.0));
                |                                        ^~~
          Main.c:3:28: note: in definition of macro ‘cmp’
              3 | #define cmp(a, b) _Generic(b, int : cmpInt, float: cmpFloat)(a,b)
                |    
          

          Ce que fait cmp, c'est juste appeler une fonction qui dépend du type de b (doc ici: https://www.iso-9899.info/n1570.html#6.5.1.1).
          AprÚs si l'appelle de fonction déroulée pas la macro n'est pas bon, le compilateur va le remarquer.
          Dalleur utiliser default n'est généralement pas une super idée.

          si tu veux faire la mĂȘme chose avec des macros en C++, ça va peu ĂȘtre plus compliquĂ©.

          Cette remarque n'Ă©tait pas pour dire que _Generic > template, mais que si tu essayes de reproduire le comportement des template C++ en macro C++, ça va effectivement ĂȘtre compliquĂ©, et hasardeux.

    • [^] # Re: l'article est intĂ©ressants

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

      Bon les destructeurs, je suis d'accord que ça manque au C,

      Mais gnu C, implémente une extension __atribute__((cleanup())), qui est implémenté par gcc, clang, tinycc, intel compiler, et est utilisé dans flatpak, systemd, et libvirt pour ne citer que quelques exemples.

    • [^] # Re: l'article est intĂ©ressants

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

      L'autre Ă©norme avantage de c++ c'est que la base de code principale peu dans son immense majoritĂ© ĂȘtre reprise telle quelle. Par contre
 bonjour les tests de non rĂ©gression


      C'est un piÚge, plus les versions de C et de C++ avancent, plus il y a des différences subtiles entre les deux et il faut faire attention.

      La base de code du noyau est grande, des subtilités bas niveau s'y glissent en plus des subtilités liées à chaque architecture ou du modÚle mémoire. Cela n'est pas trivial à introduire sans risquer de casser quelque chose.

      L'autre problÚme c'est maintenir le code. Qui va relire ou maintenir le code C++ ? Les développeurs actuels maitrisent le C, mais pas forcément le C++. Et non le C++ ce n'est pas juste du C en mieux, ça reste un langage trÚs distinct qui nécessite une expertise comme pour le C si on veut éviter les conneries.

      Et alors que Rust est introduit, ajouter un 3e langage majeur dans le code est-ce vraiment soutenable en tenant compte de ces critĂšres ? Rust montre bien que l'exercice n'est pas trivial mĂȘme si Ă  priori la barriĂšre pour le C++ est moins haute.

      • [^] # Re: l'article est intĂ©ressants

        Posté par  . Évalué à 2.

        Je pense que l'approche Rust est de prendre un langage qui :
        - est trÚs différent, donc pas de confusion possible, pas de mélange des genres.
        - apporte une réelle plus value pour les besoins du noyau.

        Le C++ a contrario expose au risque de croire que c'est quasiment comme du C et donc de faire des erreurs grossiĂšres tout en apportant pas de gain majeur sur ce qui compte vraiment.

Suivre le flux des commentaires

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