Le C++ est un langage bien présent et depuis longtemps dans les logiciels libres (environnements de bureau, outils bureautiques, navigateurs Web…). L’an 2017 approche à grands pas avec la promesse d’un tout nouveau C++17.
Pour finir l’année, voici le calendrier de l’Avent du C++ avec des dépêches pédagogiques sur ce qui nous attend en 2017. Après deux dépêches de mise‐en‐bouche, nous entrons enfin dans le vif du sujet avec deux spécifications techniques concernant l’ordre d’évaluation des expressions. Allez, c’est parti ! ᕕ(ᐛ)ᕗ
Sommaire
- Série de dépêches C++
- Spécifications Techniques
- Anecdote
- Explications
- Détails
- Autres exemples
- Conséquence
- Nouvelle règle
- Appel à participation
- Réutilisation
- Les auteurs
- Continuer à améliorer ce document
- La suite
Série de dépêches C++
Cette dépêche fait partie de toute une série disponible également sur le dépôt Git du Groupe des Utilisateurs C++ Francophone. Alors que cet article restera figé sur le site LinuxFr.org, il continuera d’évoluer sur le dépôt Git. Merci de nous aider à maintenir ce document à jour avec vos questions/suggestions/corrections. L’idée est de partager ce contenu libre et de créer/enrichir des articles Wikipédia quand la licence sera CC BY-SA 4.0.
Publication | Dépêche |
---|---|
20 août 2016 | Les coulisses du standard C++ |
2 oct. 2016 | Genèse du C++17 |
1ᵉʳ déc. 2016 | C++17 fixe l’ordre d’évaluation des expressions |
à venir… | … d’autres dépêches … |
en 2017 | Faut‐il continuer à apprendre le C++ ? |
Initialement, nous allions publier une grosse dépêche super trop longue. Puis, fin novembre, nous prenions conscience que les lecteurs apprécieraient plutôt une petite dépêche par jour, d’où l’idée de faire le calendrier de l’Avent du C++. (ღˇ◡ˇ)~♥
Spécifications Techniques
Deux TS ont été amendés par le comité de normalisation du C++ afin de fixer l’ordre d’évaluation des expressions :
- P0145 définit les changements nécessaires au standard C++ ;
- P0400 reformule une phrase de cette précédente TS P0145.
Anecdote
Le livre mythique The C++ Programming Language de l’inventeur du C++, Bjarne Stroustrup contient une erreur subtile à la page 1046 du paragraphe 36.3.6 STL‐like Operations (quatrième édition publiée en 2013). Sauras‐tu la retrouver ? Voici l’extrait en question :
The
replace()
replaces one substring with another and adjusts thestring
’s size accordingly. For example:void f() { string s = "but I have heard it works even if you don't believe in it"; s.replace(0,4,""); // erase initial "but " s.replace(s.find("even"),4,"only"); s.replace(s.find(" don't"),6,""); // erase by replacing with "" assert(s=="I have heard it works only if you believe in it"); }
A
replace()
returns a reference to the object for which it was called. This can be used for chaining operations:void f2() { string s = "but I have heard it works even if you don't believe in it"; s.replace(0,4,"").replace(s.find("even"),4,"only").replace(s.find(" don't"),6,""); assert(s=="I have heard it works only if you believe in it"); }
Pas trouvé ? Pas d’inquiétude, aucun humain n’avait trouvé cette erreur. Bien après la publication de ce livre, cette erreur a été trouvée, non pas par une nouvelle forme d’intelligence artificielle, mais juste par un outil d’analyse statique de code source au nez et à la barbe des pointures C++ aguerries.
Explications
Pour des questions de performance, le standard C++ (avant C++17) indique que c’est le compilateur qui optimise l’ordre d’évaluation du chaînage et des paramètres de fonction. Le standard utilise le terme unsequenced (séquencement non défini). Le C et le C++ partagent ensemble cette règle.
Donc, l’expression replace(find()).replace(find())
dans la fonction f2()
peut être évaluée dans des ordres différents. En théorie, la variable s
pourrait donc contenir différents résultats. Et c’est aussi le cas en pratique :
Compilateur | Résultat contenu par la variable s
|
---|---|
GCC et MSVC | I have heard it works evenonlyyou donieve in it |
LLVM/Clang | I have heard it works only if you believe in it |
Détails
Ci‐dessous, la première ligne déclare et initialise un objet std::string
. La seconde ligne cherche et remplace plusieurs caractères de cette std::string
en utilisant le chaînage des fonctions replace
:
std::string s = "but I have heard it works even if you don’t believe in it";
s.replace(0,4,"").replace(s.find("even"),4,"only").replace(s.find(" don’t"),6,"");
Intuitivement, on s’attendrait à évaluer les arguments des fonctions comme find("even")
juste avant d’appeler replace(resultat,4,"only")
. Mais ce n’est pas le cas avant C++17, ces arguments peuvent être évalués dans différents ordres. Plus de détails sont donnés par Shafik Yaghmour (en anglais).
Le tableau ci‐dessous présente sur chacune des sept lignes, un ordre d’appel possible selon les standards C++ (avant C++17) et C (en supposant que ce soit une struct string
avec des pointeurs de fonction) :
1ᵉʳ appel | 2ᵉ appel | 3ᵉ appel | 4ᵉ appel | 5ᵉ appel |
---|---|---|---|---|
find(" don’t") |
find("even") |
replace(0,4,"") |
replace(f,4,"only") |
replace(f,6,"") |
find("even") |
find(" don’t") |
replace(0,4,"") |
replace(f,4,"only") |
replace(f,6,"") |
find(" don’t") |
replace(0,4,"") |
find("even") |
replace(f,4,"only") |
replace(f,6,"") |
find("even") |
replace(0,4,"") |
find(" don’t") |
replace(f,4,"only") |
replace(f,6,"") |
replace(0,4,"") |
find(" don’t") |
find("even") |
replace(f,4,"only") |
replace(f,6,"") |
replace(0,4,"") |
find("even") |
find(" don’t") |
replace(f,4,"only") |
replace(f,6,"") |
replace(0,4,"") |
find("even") |
replace(f,4,"only") |
find(" do’'t") |
replace(f,6,"") |
C++17 n’autorise qu’une seule possibilité, la dernière du tableau, et correspond à celle de la fonction f()
du livre :
s.replace(0, 4, "");
s.replace(s.find("even"), 4, "only");
s.replace(s.find(" don't"), 6, "");
Autres exemples
Par exemple, dans l’expression f().g(h())
la fonction f()
peut être appelée avant ou après h()
. Le standard C++ fait la différence entre unspecified (non spécifié) et unsequenced (non séquencé). Ce comportement est bien spécifié, donc jusqu’à C++14, c’est unsequenced. À partir de C++17, c’est f()
avant h()
(sequenced before).
// Avant C++17, f() peut être appelée avant ou après h()
f().g( h() );
// C++17 est plus intuitif : f() est toujours appelée avant h()
C’est aussi le cas de l’expression std::cout << f() << g() << h();
dont les trois fonctions peuvent être appelées dans n’importe quel ordre :
// Avant C++17, le compilateur décide l’ordre d’évaluation de f(), g() et h()
std::cout << f() << g() << h() << std::endl;
// C++17 fixe l’ordre intuitif : d’abord f(), puis g() et enfin h()
Encore d’autres exemples que le C++ partage avec le C :
std::map<int, int> m;
m[0] = m.size();
std::cout << m[0]; // Affiche 0 ou 1 ?
// Clang : 0
// GCC : 1
// MSVC++ : 0
int i = 0;
std::cout << i << ' ' << i++; // Affiche 0 0 ou 1 0 ?
// Clang : 0 0
// GCC : 1 0
// MSVC++ : 1 0
int i = 0;
i = i++ + 1; // unsequenced
std::cout << i; // Quelle valeur ?
// Clang : 1 mais avertit : multiple unsequenced modifications to 'i'
// GCC-6.2 : 1 mais avertit : operation on 'i' may be undefined
Ci‐dessus, pour toutes les versions du C++ et du C, l’opération est unsequenced et non pas undefined, comme GCC-6.2 le laisse supposer :
int i = 0;
i = ++i, i++, i++, ++i, ++i, ++i, i++;
std::cout << i; // Quelle valeur ?
// Piège, toujours 7 car c'est "sequenced before"
// GCC-6.2 avertit : operation on 'i' may be undefined
Notons que GCC-6.2 suppose encore que l’opération est undefined, alors que dans ce dernier cas l’opération est sequenced before, quelle que soit la version du C++ (et même du C).
Conséquence
Donc, de nombreux codes source sont potentiellement truffés de ces pièges, ce qui est également le cas quand std::future<T>
est utilisé. Tout le monde se fait avoir, débutants comme experts. Et le comité de normalisation du C++ a donc amendé sans trop discuter ce TS, afin de fixer l’ordre d’évaluation dans certains cas.
Et c’est justement cet exemple du livre The C++ Programming Language qui illustre le paragraphe 5.2.2 Function call (page 107) du standard C++ (brouillon de juillet 2016).
Nouvelle règle
L’évaluation est :
- de la gauche vers la droite pour les expressions suffixées. Ceci inclut les appels de fonction et la section des membres ;
- l’affectation de la droite vers la gauche (
a = b = c = d
) ; - les opérateurs de décalage (shift operators) de la gauche vers la droite.
En revanche, lorsqu’une surcharge d’opérateur est invoquée, la priorité arithmétique est utilisée.
Peut‐être que le code généré sera moins performant, et que les standards C et C++ divergent un peu plus, mais, au moins, le langage C++ devient un peu plus intuitif.
¯\(ツ)/¯
Appel à participation
La précédente dépêche a reçu 227 commentaires, soit un volume dix fois supérieur à la dépêche elle‐même. Tous ces commentaires cachent tout de même quelques joyeux trolls velus !
Quand on pense à toute cette énergie dépensée et toutes ces heures consacrées à rédiger ces 227 commentaires ! Avec le recul, nous aurions pu concentrer tout cet investissement dans une dépêche collaborative du style « Aujourd’hui, est‐il pertinent de choisir le C++ pour une nouvelle application ? ».
Ne pas nourrir les trolls | Ne pas nourrir les trolls |
Mais il n’est jamais trop tard ! Aussi nous proposons vous de rédiger la dépêche « Faut‐il continuer à apprendre le C++ ? » Les nombreux commentaires de la dépêche précédente méritent d’y être copiés. Malheureusement, ceux‐ci sont rarement sous licence compatible CC BY-SA 4.0. Ceci est donc un appel à tous leurs auteurs pour les copier dans cette dépêche afin de la nourrir. Ainsi, nous pourrons les structurer et proposer des réponses concises, claires et utiles à tous.
Merci et à vos claviers !
Réutilisation
Le texte de cette dépêche est protégé par le droit d’auteur la gauche d’auteur et réutilisable sous licence CC BY-SA 4.0. Les images utilisées sont aussi sous licence libre (cliquer sur l’image pour plus de détails).
Donc, n’hésitez pas à réutiliser ce contenu libre pour créer, par exemple, des supports de formation, des présentations (Meetups), des publications sur d’autres blogs, des articles pour des magazines, et aussi un article C++17 sur Wikipédia dès que Wikipédia passera de la licence CC-BY-SA 3.0 à la CC-BY-SA 4.0 (le contenu de cette dépêche utilise la version la CC-BY-SA 4.0).
Les auteurs
Par respect de la licence, merci de créditer les auteurs :
- les principaux auteurs sont Adrien Jeser et Oliver H.’;
- les nombreux autres contributeurs ayant contribué sur l’ancêtre de cette dépêche ou sur le dépôt Git sont : eggman, Yves Bourguignon, Storm, gorbal, palm123, khivapia, BAud, Segfault, Benoît Sibaud, Lucas, cracky, Martin Peres, RyDroid, olibre et Guss.
Continuer à améliorer ce document
Malgré tout le soin apporté, il reste certainement des oublis, des ambiguïtés, des fôtes… Bien que cette dépêche restera figée sur le site LinuxFr.org, il est possible de continuer à l’enrichir sur le dépôt Git du Groupe des utilisateurs C++ francophone (C++FRUG). C’est donc sur ce dépôt que se trouvent les versions les plus à jour. (ღ˘⌣˘ღ)
La suite
Nous venons de découvrir un changement important au niveau du langage. La dépêche suivante nous dévoilera une autre nouveauté du C++17.
Chère lectrice, cher lecteur LinuxFr.org. Tu souhaites apporter ta pierre à cet édifice ? Rejoins‐nous dans l’espace de rédaction collaborative sur LinuxFr.org (un compte est nécessaire pour y accéder).
À suivre…
Aller plus loin
- Dépêche préliminaire dans « Les coulisses du standard C++ » (CC BY-SA 4.0) (225 clics)
- Dépêche de mise en bouche racontant la genèse du C++17 (CC BY-SA 4.0) (158 clics)
- Contenu markdown de cette dépêche sur le dépôt Git du C++FRUG (145 clics)
- Mars 2016 : Réunion pour dresser un premier contour du C++17 (Herb Sutter) (119 clics)
- Mars 2016 : Détail de cette même réunion du comité de normalisation du C++ (Botondballo) (116 clics)
- Juin 2016 : Réunion pour finaliser le périmètre C++17 (Herb Sutter) (115 clics)
- Liste concise des nouveautés C++17 sur StackOverflow (Yakk, CC BY-SA 3.0) (155 clics)
- Liste partielle des nouveautés C++17 sur MeetingC++ (Jens Weller) (120 clics)
- Article Wikipédia C++17 (CC BY-SA 3.0) (151 clics)
- Principaux apports des C++11/14/17 (Anthony Calandra, MIT) (151 clics)
# Génial
Posté par David Demelier (site web personnel) . Évalué à 7.
Alors ça c'est vraiment un moyen de résoudre des bugs subtiles car beaucoup de débutants ne savent pas que l'ordre est non-défini.
Surtout que la plupart des livres que j'ai lu n'en parlaient pas.
git is great because linus did it, mercurial is better because he didn't
[^] # Re: Génial
Posté par lmg HS (site web personnel) . Évalué à 1.
En effet, il n'y a en général guère que dans les guides qualité que l'on peut trouver des références à ces problèmes. Et encore, en général, on se contente du
f[i] = i++;
.[^] # Re: Génial
Posté par barmic . Évalué à 4.
Je suis surpris parce qu'on m'avait dit que c'était volontaire, que ça permettait de laisser plus de liberté aux compilateurs, voir que c'était lié à l'architecture matériel et à la manière dont on code l'appel d'une fonction dans l'assembleur donné.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Génial
Posté par pulkomandy (site web personnel, Mastodon) . Évalué à 1.
C'est le cas (d'ailleurs les exmples dans la dépêche montrent que certains compilateurs font des choix différents). Mais il y a toujours un compromis entre "on laisse le compilateur faire le truc le plus rapide possible" et "on fait un truc qui fonctionne comme attendu". Par exemple, le comportement du modulo sur les nombres négatifs n'était pas défini en C89, mais il l'est devenu en C99.
[^] # Re: Génial
Posté par Thomas Douillard . Évalué à 2.
En même temps si le compilateur rend un programme vide mais super optimisé alors que le développeur attendais à ce qu'il fasse quelque chose parce qu'il a été super malin en trouvant un bug de la spec qui fait interpréter ton code par un no-op, certes il a eu de la liberté mais toi tu seras pas plus avancé ;)
[^] # Re: Génial
Posté par barmic . Évalué à 3.
C'est pour un peu contrebalancer les discours un peu « droit dans mes bottes » sur d'autres aspects : « si ce n'est pas standardisé, c'est que ces problèmes ne pourront sans doute jamais être résolus de manière sûre » source.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
# Correction
Posté par Achille Fouilleul (site web personnel) . Évalué à 2.
s/assignement/affectation/
[^] # Re: Correction
Posté par Benoît Sibaud (site web personnel) . Évalué à 3.
Corrigé, merci.
# Erreur de livre et experts C++
Posté par moi1392 . Évalué à 5.
Sérieux ?
Autant, je ne me serais peut être (voir certainement) pas posé de question car il s'agit en effet du livre de Bjarne, et je me serait naturellement dit que s'il l'écrivait ainsi, il devait être sûr de son coup.
Mais quand même, quand je vois ça :
s.replace(0,4,"").replace(s.find("even"),4,"only").replace(s.find(" don't"),6,"");
En sachant à l'avance qu'il y avait une erreur dans le code, je n'ai pas hésité une seule seconde, et je ne me défini absolument pas comme un expert C++, donc me dire qu'aucun expert ne l'avais vu, ça me surprend énormément !
Perso, je vois ça dans du code dans la boite où je bosse, le mec qui l'a écrit a droit une courtoise comparaison avec de charmants animaux ayant des pratiques sexuelles réprouvées par la morale et le code et réécrit dans une forme où le doute n'est plus possible illico !
[^] # Re: Erreur de livre et experts C++
Posté par Oliver (site web personnel) . Évalué à 1.
Oui, c'est sûr, les humains n'auraient pas pensé remettre en cause les écritures saintes du C++.
Mais les algorithmes ont moins d'état d'âme ;-)
Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
[^] # Re: Erreur de livre et experts C++
Posté par Lutin . Évalué à 2.
C'est pas sympa d'insulter les gens qui font des erreurs.
[^] # Re: Erreur de livre et experts C++
Posté par barmic . Évalué à 10.
Ce n'est pas le fait qu'il y ai une erreur qui l'embête à mon avis, mais plus le fait de chaîner de manière illisible les traitements. Oui c'est illisible, quand on met des années à voir le bug alors qu'il est scruter par un grand nombre de spécialistes du langage.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Erreur de livre et experts C++
Posté par moi1392 . Évalué à 9.
C'est exactement ça, ce qui m'embête, c'est le fait d'écrire du code qui est ambigu et qui laisse le doute à la lecture.
Surtout que dans le cas présent, ça ne dois pas coûter beaucoup plus cher d'écrire une ligne à la fois !
Quand tu bosses à beaucoup sur un projet, qui a une base de code énorme sur plus de 20 années d’existence, et des tas de développeurs différents qui sont passés dessus, à un moment il faut limiter les risques !
Et avoir des pratiques saines limite en effet les risques !
aucun langage n'est sûr, tu peux toujours écrire des choses qui vont avoir un effet inattendu, mais à un moment, dans un langage comme le c++ qui te permet de faire des choses plus dangereuses que d'autres langages, si en plus tu te mets à écrire ce genre de choses, la catastrophe est assurée !
[^] # Re: Erreur de livre et experts C++
Posté par Oliver (site web personnel) . Évalué à 3.
Nous sommes tous d'accord avec toi pour dire qu'une ligne aussi peu compréhensible comme celle-là n'est pas une bonne pratique.
L'auteur du livre l'avait donné en exemple juste pour illustrer le chaînage.
Ce n'est absolument pas pour inciter les développeurs à chaîner toutes les fonctions qui supporte le chaînage.
Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
[^] # Re: Erreur de livre et experts C++
Posté par moi1392 . Évalué à 7.
Je pense aussi qu'il s'agit d'un exemple pour illustrer une propos.
Mais cela montre bien que la langage est dangereux si on l'utilise sans se poser de questions, car même son auteur, dans un livre qui est sensé faire référence, à commis une erreur !
Et ce qui me surprends le plus dans le cas présent, c'est que personne n'avait remarqué !
Je ne jette la pierre à personne, si j'avais du lire ce livre, je ne pense pas que la lecture de cette ligne m'aurais fait bondir, car elle sert seulement d'exemple et n'est pas vouée à piloter les moteurs de la prochaine fusée Ariane 42 !
Mais une fois encore, je ne me qualifie pas d'expert, et en sachant à l'avance qu'il y a une erreur, je tout de suite vu où et quelle était cette erreur.
Du coup je suis très surpris qu'aucun vrai expert ne l'ai vu !
[^] # Re: Erreur de livre et experts C++
Posté par groumly . Évalué à 7.
Disons qu'utiliser un objet comme paramètre a une méthode qui modifie l'objet en question, et chaîner le tout, c'est un peu chercher les coups.
Ordre défini ou pas, c'est trop facile de rater quelque chose.
Linuxfr, le portail francais du logiciel libre et du neo nazisme.
[^] # Re: Erreur de livre et experts C++
Posté par foobarbazz . Évalué à 1.
Et c'est même pas un humain qui l'a trouvé ce bug, c'est une machine ^
[^] # Re: Erreur de livre et experts C++
Posté par xryl669 . Évalué à 5.
C'est sûr, alors qu'une bonne expression régulière aurait fait des miracles en un seul appel.
Ceci dit, le pattern Fluent est vraiment agréable à utiliser (pour ceux qui font du JQuery, lodash, etc… par exemple, impossible de penser autrement maintenant).
Le vrai problème du code ci dessus vient de la signature de la fonction replace qui modifie la chaîne au lieu de retourner une nouvelle string. Si cela avait été le cas, alors l'ordre d'appel, on s'en balance. Avec un replace immutable, alors il faut, logiquement faire la recherche de la sous chaîne par la fin pour garantir que les modifications soient appliquées au bon endroit.
Mais au final, on retombe encore sur les signatures bancales de la classe string, qui ne propose qu'un nombre limité de méthodes (au nom d'une simplification de l'implémentation STL, mais qui, en pratique, force chaque projet à réimplémenter les fonctions de bases avec tous les bugs que ça impliquent). Un string replace(const string & this, const string & by_that) serait alors bien plus simple et dans la majorité des cas (le reste, c'est faisable par un erase + insert). De même pour tout ce qui est basé sur des index en fait, dans la majorité des cas, c'est inutile et vraiment pénible dès lors que l'on fait du UTF-8.
Un code comme ceci est bien plus compréhensible:
String s = "The blue cat doesn't like the yellow dog";
return s.replace("yellow", "blue").replace("blue", "yellow").replace("dog", "cat").replace("cat", "dog");
// Autre exemple, plus concret
String get_authority(const String & url) {
// Exemple: url = "http://whatever.org/path/to/index.html";
return url.from_first("://").to_first("/");
}
Le deuxième exemple, montre que, même si en interne la classe utilise des index pour trouver les sous chaînes, ils ne sont pas visibles dans la signature des méthodes, et donc c'est carrément plus intuitif. Côté performance, avec du COW, c'est mieux que du code à base de find & replace, vu qu'il ne faut plus "sortir" les index de la stack dans les fonctions supérieures, une seule fonction appelée, moins de registres utilisés et donc, au final, tourne beaucoup plus vite.
[^] # Re: Erreur de livre et experts C++
Posté par barmic . Évalué à -1.
Le problème n'est pas l'API fluent, écrire ça :
Ne pose aucun problème.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Erreur de livre et experts C++
Posté par pulkomandy (site web personnel, Mastodon) . Évalué à 6.
Sauf que ça marche pas non plus!
Tu as reproduit le même bug: le premier replace déplace tous les caractères, et tes offsets (even et dont) ne sont plus au bon endroit sur la nouvelle chaîne.
[^] # Re: Erreur de livre et experts C++
Posté par barmic . Évalué à 5.
Effectivement, je me suis raté.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Erreur de livre et experts C++
Posté par lmg HS (site web personnel) . Évalué à 1.
Pas besoin de payer pour du COW. Le déplacement marcherait très bien si on travaille sur une chaine sans changer sa taille.
Maintenant, dans "classe string, qui ne propose qu'un nombre limité de méthodes", je lis : "rajoutons des fonctions membres à
std::string
". Pitié non il y en a déjà bien assez dedans, et pas assez dehors.Résultat avec l'arrivée des
string_view
on va se payer une surcharge de trucs déjà écrits, ou l'impossibilité d'utiliser ce boost de performance et d'API unifiée. C'est bien idiot. Je vois régulièrement des projets qui n'ont rien trouvé de mieux à faire que de créer leur propre classe de chaine juste pour rajouter des fonctions membres dedans au lieu de les fournir en libre. Résultat ils écrivent des choses dont ne on pourra pas profiter sur lesstring_view
—ou des équivalentes que l'on pourrait vouloir écrire.[^] # Re: Erreur de livre et experts C++
Posté par barmic . Évalué à 6.
C'est typiquement l'un des meilleurs argument au duck/structural typing :)
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Erreur de livre et experts C++
Posté par xryl669 . Évalué à 4.
C'est marrant, j'ai exactement l'avis opposé. Je trouve beaucoup plus intuitif de faire obj.methode() pour une action que func(obj).
Mon commentaire, n'était pas pour ajouter des méthodes à std::string, mais pour dire que l'interface initiale est pourrie, car trop basée, comme pour les premières classes de la STL, sur des idées 1980 (code ASCII 8bits, tout le monde parle anglais, etc…), et pas assez sur l'utilisation de l'objet lui-même. Dans la réalité des codes utilisant du std::string que j'ai lu (et j'en lis beaucoup), 99.9% du temps, les indices sont inutiles, plein de bugs, etc…
L'exemple le plus flagrant, c'est lorsque je dois faire l'i18n d'une appli C++. Le développeur ne sait pas (ou a "oublié") qu'il travaillait avec de l'UTF-8, et estime, à tort que l'index d'un caractère est égal à sa position en mémoire. Avec une interface sans index à gérer, il n'y a aucun soucis. Avec std::string, c'est l'horreur. Avec une classe utilisant le pattern "from_first", "upto_last", etc, ça roule tout seul.
Traduire le code des iostreams c'est aussi une autre hérésie qui n'aurait jamais dû survivre à plus d'un standard. Le grand classique, que j'ai vu à de nombreuses reprises, c'est
"cout << "There is " << animal_count << " pet" << animal_count ? 's' : '\0' << " in the store."<< endl;
En général, là, le code est à réécrire (grand moment de solitude). Franchement, séparer la présentation des données, même le C le faisait en 89 avec printf et gettext, le C++ n'y est toujours pas (il y a boost::format mais bon… boost quoi…).
De plus, l'interface des string aurait due être séparée en "méthodes" non modifiantes, "méthodes modifiantes", quitte à faire une classe "readonly_string" qui permette les recherches, les modifications de taille (ou du pointeur de début de chaîne) mais pas du contenu de la chaîne (bref: tout ce qui est requis pour parser du texte), et une classe "writeable_string" pour le reste, en ayant un héritage multiple des deux interfaces dans ce qui s'appelle la classe string. Du coup, la problématique du COW disparaît automatiquement suivant que l'on veuille en payer le prix ou non (pour le parsing, par exemple, pas de COW pour du RO).
[^] # Re: Erreur de livre et experts C++
Posté par barmic . Évalué à 2.
C'est la même chose, mais les IDE peuvent t'aider à chercher avec la notation pointée.
Le fait de ne pas avoir d'interface ne doit pas aider…
Oui et d'ailleurs pas forcément en UTF-8, hein ? Ça peut aussi être de l'UCS2 par exemple.
C'est joli mais pas beau peut être qu'en ajoutant un opérateur
%
pour faire :Pourrait être mieux
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Erreur de livre et experts C++
Posté par pulkomandy (site web personnel, Mastodon) . Évalué à 1.
On est en C++ là. Il suffit de faire une const std::string. Les méthodes que tu peux utilisées sont alors uniquement celles annotées "const", qui ne modifient pas le contenu de l'objet. Pas besoin d'une deuxième classe.
Cela dit, il me semble qu'il y a dans les projets pour C++17 une "string_view", qui ne stocke pas ses données mais permet de faire ce genre de choses avec des données externes (venant d'une string, d'un char*, ou d'une autre string_view), ceci afin de limiter le nombre de copies des données.
[^] # Re: Erreur de livre et experts C++
Posté par lmg HS (site web personnel) . Évalué à 2.
Je suis de plus en plus de l'avis que ce n'est que du sucre syntaxique. Sucre qui de par sa forme bride le polymorphisme sur un seul argument. Dans un monde où l'on aurait des multimethods (Stroustrup et d'autres y travaillent, pour après le C++17 donc), çà donnerait
(o1,o2).method
avec la syntaxe point, mais d'autres langages ont choisi[message o1 o2]
(ou des trucs approchants que je peux retrouver).Bref, je regrette un peu que l'Unified Call syntax n'ai pas été retenue pour le C++17: https://isocpp.org/blog/2016/02/a-bit-of-background-for-the-unified-call-proposal
Et quid des types natifs? Dans une fonction générique, on pourrait écrire juste
trim(machaine)
quemachaine
soit unestd::string
, unestd::string_view
, uneQString
, uneCString
, uneossimString
… ou tout simplement un tableauchar(&)[N]
, ou encore un pointeur sur chaine 0-terminéechar*
. Avec l'écriture point, on perd les deux dernières possibilités.Entièrement d'accord qu'il y a plein de soucis, même avec boost.locale (surcouche C++ à ICU), cela reste assez peu intuitif à manipuler.
Ce que tu décris ressemble à
std::(experimental::)string_view
. C'est justement la raison pour laquelle je suis persuadé que l'extension d'interface par l'extérieur (on retrouve un des items de (More?) Exception C++ de Sutters—dispo sur http://gotw.ca/gotw aussi) est préférable.Sur les Cpp Core Guideline, on retrouve les mêmes principes avec les
span
. Et on voit vite que l'on n'a pas besoin d'héritage, que c'est simple, que cela ne nécessite pas d'écrire des fonctions templates, et que c'est aussi efficace que le couple pointeur+taille du C.Sinon, ce sujet me rappelle la profusion de classes pour les chaines de caractères dans Adobe.ASL. Là, on a toujours un outil ad'hoc, mais c'est plus complexe pour le pékin moyen que nous sommes qui préfère un seul type pour les unir toute, à la
QString
.D'accord aussi que produire uniquement des nouvelles chaines (à la mode fonctionnelle: i.e. pas d'altération d'état) aurait pu être pal mal du tout.
Pour les flux, oui, c'est une catastrophe pour l'i18n. Sur le sujet, je teste spdlog et la bibliothèque de formattage sous-jacente en ce moment.
[^] # Re: Erreur de livre et experts C++
Posté par btc . Évalué à -1.
bah putain, donne moi le nom de ta boite, que je n'y postule jamais !
[^] # Re: Erreur de livre et experts C++
Posté par xcomcmdr . Évalué à 5.
? C'est pourtant pas bien compliqué, ni mauvais, de ne pas faire de train wrecks !
Mais je suis d'accord pour que tu n'y postules jamais, si c'est pour écrire du code aussi difficile à lire. j'ai déjà eu trop de boulot qui consistait à "passer derrière les porcs". :(
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
[^] # Re: Erreur de livre et experts C++
Posté par moi1392 . Évalué à 4.
Ne t'inquiète pas, si tu écris ce genre de choses, quand bien même tu y postulerais par erreur ou inadvertance, il y a peu de chances pour que tu y sois embauché.
[^] # Re: Erreur de livre et experts C++
Posté par David Marec . Évalué à 4.
Je trouve aussi que l'exemple est assez mal choisi, on doit rarement rencontrer ce genre d'enfilades en C++.
Par contre, je suis déjà tombé sur ce même problème, mais avec des
stream
, pour lesquelles enfiler des fonctions/entrées est l'usage:Où les appels des premières méthodes affectent le résultat, qui sera donc différent selon l'ordre d'exécution.
De mémoire MSVC évaluait de droite à gauche alors que GCC et CLang évaluaient de gauche à droite.
[^] # Re: Erreur de livre et experts C++
Posté par David Marec . Évalué à 6.
Exemple:
Visual studio 2012:
2 1 1
Clang 3.4.1 :
2 4 4
je n'ai pas de GCC sous la main
[^] # Re: Erreur de livre et experts C++
Posté par barmic . Évalué à 5.
Avec gcc (Debian 4.9.2-10) :
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Erreur de livre et experts C++
Posté par David Marec . Évalué à 2.
En effet.
- Il me semble pourtant avoir obtenu
2 4 4
avec un GCC. -Ceci dit, le développeur qui a écrit ce code, ainsi que tous ceux qui l'on lu et qui ont cherché d'où venait la boulette , s'attendait à avoir comme résultat
2 4 4
.# Faut-il continuer à apprendre le C++ ?
Posté par Victor STINNER (site web personnel) . Évalué à 1.
non
[^] # Re: Faut-il continuer à apprendre le C++ ?
Posté par Antoine . Évalué à 4.
Ici une réponse laissée indéfinie par le standard et dépendant du bon vouloir du compilateur (oui, non, 42, -32768, dépassement d'addition signée, NaN).
[^] # Re: Faut-il continuer à apprendre le C++ ?
Posté par DerekSagan . Évalué à 5.
C++ c'est nul parce qu'il y a des ambiguïtés, à la place il faut apprendre javascript, parce que tout le monde peut deviner naturellement ce que font par exemple 0+'' ou si undefined+0+'' est égal à undefined+''+0 ou non.
# Licence
Posté par barmic . Évalué à 4.
J'en profite pour modifier ma signature si ça peut simplifier la vie à certains :)
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Licence
Posté par pulkomandy (site web personnel, Mastodon) . Évalué à 1. Dernière modification le 01 décembre 2016 à 12:02.
Il te manque un T à "mes écrits".
(et si vous voulez réutiliser mes commentaires pour la prochaine dépêche, pas de problème)
[^] # Re: Licence
Posté par barmic . Évalué à 1.
Corrigé ! Merci :)
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Licence
Posté par Chuck #1 . Évalué à 2.
Et si vous voulez réutiliser ma signature, y'a pas de problème.
Cette signature est publiée sous licence WTFPL
# Coquille
Posté par serge_sans_paille (site web personnel) . Évalué à 1.
Je pense que c'est c’est f() avant h() (sequenced before)
Sinon excellent journal, le dessin m'a bien fait marrer !
[^] # Re: Coquille
Posté par Benoît Sibaud (site web personnel) . Évalué à 3.
Corrigé, merci.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.