CppCon 2016 : Bjarne Stroustrup parle de l'évolution de C++ et s'intéresse à son passé
à son présent mais aussi à son futur
Le 2016-09-23 23:24:55, par Stéphane le calme, Chroniqueur Actualités
Durant l’édition 2016 de la conférence annuelle de la communauté C++ CppCon, le professeur de science informatique danois et créateur du langage Bjarne Stroustrup a tenu à présenter les évolutions du langage, notamment en évoquant son passé, son présent, mais également son futur.
« Je me demandais ce dont j’allais parler durant cette conférence en tant qu’orateur. Puis j’ai regardé le programme et j’ai réalisé qu’il y avait une grosse liste de choses bien détaillées, que ce soit sur le langage, les bibliothèques, etc. Aussi, je me suis dit que je n’allais pas me lancer dans cette voie. J’essaie au contraire de parler de quelque chose de plus général. J’essaie de parler d’évolution. J’essaie de retourner en arrière pour comprendre la raison pour laquelle C++ a connu du succès », a-t-il déclaré en guise d’introduction devant l’auditoire.
Les points sur lesquels Bjarne Stroustrup s'est appesanti sont notamment :
Durant son intervention, il a donné son avis, par exemple, sur les fonctionnalités d’un bon langage de programmation. Selon lui, bien que tout langage ait besoin de bonnes fonctionnalités fondamentales (par exemple, des mécanismes pour aider à concevoir son code, mais également une bibliothèque standard), un (bon) langage ne saurait se limiter à être un ensemble de bonnes fonctionnalités.
Il s’est également attardé sur les décisions majeures qui ont été prises dans la conception du langage et a indiqué sur une ligne du temps leur impact sur la façon de programmer des développeurs.
Il a expliqué que, pour sa part, les fonctionnalités majeures sont celles qui changent la façon dont les gens pensent le code, tout comme les concepts, qui devraient arriver dans la prochaine version de C++. Il a néanmoins indiqué qu’une combinaison de fonctionnalités mineures peut avoir un impact majeur.
À la question de savoir ce qui fait une bonne extension, il explique que les réponses sont très variées. Du point de vue des développeurs, une bonne extension « aide les gens comme moi et mon projet » :
Les difficultés rencontrés par les développeurs lors de la conception d’une extension sont :
Du point de vue des concepteurs, une bonne extension « va aider de façon significative la communauté des utilisateurs pendant la prochaine décennie » :
Malgré tout, il a reconnu que toutes les extensions font plus ou moins de mal :
Tous ces critères ont aidé à façonner C++17. Ainsi, des modifications dont les effets sont relativement isolés ont été acceptées sans problème, comme de simples variables globales, c'est-à-dire la syntaxe inline int x = f();. Au contraire, la convention d'appel unifiée a été rejetée : elle proposait que l'écriture f(x) soit équivalente à x.f() dans tous les cas.
Dans son intervention, il évoque de nombreux points intéressants relatifs à l'évolution de C++.
Source : YouTube
Voir aussi :
CppCon : Bjarne Stroustrup annonce le projet C++ Core Guidelines, pour aider les développeurs à utiliser le C++ moderne de façon plus efficace
« Je me demandais ce dont j’allais parler durant cette conférence en tant qu’orateur. Puis j’ai regardé le programme et j’ai réalisé qu’il y avait une grosse liste de choses bien détaillées, que ce soit sur le langage, les bibliothèques, etc. Aussi, je me suis dit que je n’allais pas me lancer dans cette voie. J’essaie au contraire de parler de quelque chose de plus général. J’essaie de parler d’évolution. J’essaie de retourner en arrière pour comprendre la raison pour laquelle C++ a connu du succès », a-t-il déclaré en guise d’introduction devant l’auditoire.
Les points sur lesquels Bjarne Stroustrup s'est appesanti sont notamment :
- le passé : pourquoi est-ce que C++ a connu le succès ?
- en répondant aux questions avant que les gens ne les posent,
- en ne suivant pas la masse ;
- le présent : comment la standardisation façonne-t-elle le C++ ?
Elle aspire à la stabilité via la compatibilité ; - le futur : que devons-nous faire ?
- concentrer nos efforts à servir la communauté C++ actuelle et à venir,
- ne pas se dissiper en essayant de plaire à tous ;
- le futur proche : comment s'y préparer ?
- trouver des moyens pour utiliser des fonctionnalités des spécifications techniques ISO,
- développer des lignes directrices.
Durant son intervention, il a donné son avis, par exemple, sur les fonctionnalités d’un bon langage de programmation. Selon lui, bien que tout langage ait besoin de bonnes fonctionnalités fondamentales (par exemple, des mécanismes pour aider à concevoir son code, mais également une bibliothèque standard), un (bon) langage ne saurait se limiter à être un ensemble de bonnes fonctionnalités.
Il s’est également attardé sur les décisions majeures qui ont été prises dans la conception du langage et a indiqué sur une ligne du temps leur impact sur la façon de programmer des développeurs.
Il a expliqué que, pour sa part, les fonctionnalités majeures sont celles qui changent la façon dont les gens pensent le code, tout comme les concepts, qui devraient arriver dans la prochaine version de C++. Il a néanmoins indiqué qu’une combinaison de fonctionnalités mineures peut avoir un impact majeur.
À la question de savoir ce qui fait une bonne extension, il explique que les réponses sont très variées. Du point de vue des développeurs, une bonne extension « aide les gens comme moi et mon projet » :
- elle résout des problèmes spécifiques ;
- elle ne nécessite pas de lecture fastidieuses de mode d’emploi ;
- elle isole le changement ;
- elle n’entraîne pas de plantage.
Les difficultés rencontrés par les développeurs lors de la conception d’une extension sont :
- un manque d’expérience dans la planification à long terme ;
- des objectifs très souvent définis par d’autres personnes ;
- une évaluation des conséquences sur le court terme.
Du point de vue des concepteurs, une bonne extension « va aider de façon significative la communauté des utilisateurs pendant la prochaine décennie » :
- elle répond à un problème général / fondamental ;
- elle fait que le langage est utilisé de façon plus régulière et facilement ;
- elle améliore la réputation de C++.
Malgré tout, il a reconnu que toutes les extensions font plus ou moins de mal :
- elles rendent obsolètes certains supports d’apprentissages ;
- elles peuvent avoir un faible ratio bénéfice / coût ;
- elles pourraient ne venir en aide qu’à une portion de la communauté ;
- elles pourraient induire des coûts à des personnes qui ne les utilisent pas ;
- elles pourraient être une entrave pour les efforts de pratique de programmation.
Tous ces critères ont aidé à façonner C++17. Ainsi, des modifications dont les effets sont relativement isolés ont été acceptées sans problème, comme de simples variables globales, c'est-à-dire la syntaxe inline int x = f();. Au contraire, la convention d'appel unifiée a été rejetée : elle proposait que l'écriture f(x) soit équivalente à x.f() dans tous les cas.
Dans son intervention, il évoque de nombreux points intéressants relatifs à l'évolution de C++.
Source : YouTube
Voir aussi :
-
JolyLoicRédacteur/ModérateurAs tu déjà essayé auto sur des vrais projets ? Moi, oui, et je n'ai pas rencontré les problèmes dont tu parles.
Au contraire, je trouve le code plus lisible avec auto que sans. Parce qu'il permet de s'éloigner du type d'une variable, pour se concentrer sur son rôle. Et que c'est ça qui compte le plus.
Je n'en sais rien, et je m'en moque. Ce qui compte c'est de savoir que v contient des chaînes, et quelles chaînes (est-ce que ce sont des noms, des titres, des phrases...). Savoir si ce sont des std::string, des QString, des glib::ustring... n'importe pas vraiment. C'est similaire du fameux "program to interface, not implementation" des langages comme C# ou Java.
Personne (et auto n'a jamais promis qu'on pouvait changer de type de manière 100% transparente...). Dans certains cas ça marchera, dans d'autres cas, il faudra apporter des modifications fastidieuses au code suite au refactoring. En pratique, il y a quand même pas mal de cas où ça marche, les templates ont bien formé les gens à utiliser des interfaces identiques. Mais sans auto, c'est garanti que ça ne marcherait jamais, voire pire, que ça marcherait en ajoutant silencieusement des opérations inutiles (conversion d'une chaîne en une autre, par exemple).
Si la source des variables est loin dans le code, il y a un autre problème. J'ai très rarement plus de 20 lignes entre le moment où une variable est initialisée, et le moment où elle est utilisée pour la dernière fois (c'est souvent moins de 10). Et voir comment la variable est initialisée est suffisant pour savoir quoi en faire, quand les noms de variables/fonctions sont bien choisis. Et s'ils ne sont pas bien choisis, ce n'est pas de connaître le type qui va aider.
auto str, tu ne peux rien en faire, et le compilateur non plus, on est bien d'accord. auto str = f();, je suis aussi d'accord qu'on ne peut pas en faire grand-chose non plus. Mais franchement, std::string str = f();, je saurais lui faire faire des choses, certes, mais des choses utiles ? Non. Savoir que str est une chaîne ne m'aide absolument pas à savoir ce qu'elle contient et ce qu'il faudrait que j'en fasse. auto searchCriterion = mySearchDialog.getResult();, là, oui, je commence à bien savoir qu'en faire. Et la plupart du temps, je n'ai pas besoin du tout de savoir le type exact pour manipuler mon seachCriterion. Je peux le placer dans une searchHistory, le transmettre à un searchEngine et demander à ce dernier des searchResults... Et je suis certain que tu as compris en quoi consistaient les opérations dont je parlais, alors même que je n'ai pas précisé si searchCriterion était un std::string, un QString, une std::regex, une classe (avec une string, un bool caseSensitive, et une enum normal/regex/wildcards)...
J'aurais pu écrire ce code : SearchCriterion searchCriterion = mySearchDialog.getResult();, là, il n'y a plus d'auto, mais je ne trouve pas que le code gagne en lisibilité. J'aurais aussi pu l'écrire (en supposant que je me lie au fait qu'actuellement, un searchCriterion est juste une chaîne, et que je devrais revenir là-dessus si je désire enrichir mes possibilités de recherche : std::string searchCriterion = mySearchDialog.getResult();. Est-ce pour autant que j'ai vraiment appris plus de choses sur searchCriterion ?
On pourrait me dire, "oui, tu sais que c'est une std::string, donc par exemple, tu sais que tu as le droit d'écrire if(!searchCriterion.empty()) searchCriterion[0] = 'a';". Sauf qu'en fait, c'est faux. On n'a pas le droit d'écrire ça, car c'est une chaîne de recherche, et dans mon cas, une recherche peut avoir une syntaxe spéciale, validée par mySearchDialog.getResult();, et que modifier un caractère comme ça à la hussarde peut rompre les invariants de mon code. Les invariants ne sont pas tous dans le système de type, mais aussi dans le contrat des fonctions. Ils sont sémantiques, pas syntaxiques. Ils sont donnés par les diverses fonctions qu'on appelle, celles-là même qui sont le point d'attention majeur quand on utilise auto. Et qu'utiliser auto permet justement de se focaliser sur la sémantique, en réduisant le bruit lié à la syntaxe.le 25/09/2016 à 15:17 -
GugelhupfModérateur
Envoyé par mister3957 le 24/09/2016 à 11:10 -
PyramidevExpert éminentauto a plusieurs buts. Personnellement, au quotidien, les moments où j'ai le plus envie d'utiliser auto, c'est quand j'appelle une fonction de la STL dont le type de retour est connu, mais fait 3 km.
Exemple :
Code : 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// Sans auto : { std::pair<std::map<IdUtilisateur, Utilisateur>::iterator, bool> tmp = mapUtilisateurs.insert(std::make_pair(id, utilisateur)); bool identifiantPasDejaUtilise = tmp.second; // ... } // Avec auto : { auto tmp = mapUtilisateurs.insert(std::make_pair(id, utilisateur)); bool identifiantPasDejaUtilise = tmp.second; // ... } // Avec les structured bindings de C++17 : { auto [it, identifiantPasDejaUtilise] = mapUtilisateurs.insert(std::pair(id, utilisateur)); // ... }
le 24/09/2016 à 13:27 -
JolyLoicRédacteur/ModérateurTu fais donc une classe pour les doubles positifs quand tu veux appeler sqrt, une autre pour les doubles strictements positifs quand tu veux appeler log, une autre pour les chaînes de caractères non vides, une autre pour...
J'ai essayé à un moment sur du vrai code, mais j'ai trouvé ça bien trop lourd et finalement peu utile dès que tu es lié à des bibliothèques externes qui elles n'ont pas été écrites avec tes invariants en tête. Peut-être que si je devais coder dans un domaine où des vies humaines dépendent de mon code, je regarderai à nouveau ça de plus près, même si dans ces domaines, c'est encore la preuve de code (qui n'utilise pas le typage, mais des informations sémantiques) qui semble le plus utilisé...
À partir du moment où tu parles de naviguer dans le code, on ne parle plus de la lisibilité passive, mais d'une lisibilité active. Avec mon IDE, que j'utilise auto ou pas, aller à la définition d'un type, c'est 1 touche à appuyer. Je pense que c'est plus efficace que toute stratégie qui serait basée sur une homonymie espérée entre nom de type et nom de fichier... Je ne suis donc pas très convaincu par cet argument...le 25/09/2016 à 19:18 -
jo_link_noirMembre expertC'est exactement ce qu'il dit: c'est différent.
Je pense que le reproche mister3957 vient dans la relecture d'un code qui n'utilise que auto: on perd l'information de type à la lecture. Personnellement, je trouve cette information peu utile puisqu'il reste le nom de la variable, la valeur d'initialisation et le contexte d'utilisation.
Pas plus qu'avec auto. Il y a certes une information en plus qui est le nom du type, mais cela reste un contrat implicite qui se vérifie au moment où de l'utilisation. Pas d'opérateur + ? Erreur sur la ligne qui l'utilise. Une notion de contrat devrait être vérifiée au moment de l'initialisation, comme ce que proposent les concepts.
Si j'ai bien compris les quelques trucs vu sur les concepts, ceux-ci pourront remplacer une bonne partie des types templates et auto, tout en offrant une vérification d'interface implicite via un contrat nommé.
Il y aussi une généralisation de auto jusqu'au paramètre de template pour les paramètres qui n'ont pas de contrat défini.le 24/09/2016 à 17:28 -
EhonnMembre chevronnéLa première fois que tu vois un nouveau type, il faut aller voir la documentation pour savoir comment l'utiliser / le manipuler (auto ou pas).
Maintenant, il faut soit aller voir la documentation, soit demander à son compilateur, pour connaître le type.
Non, car on "utilisait" déjà auto avant (sous une autre forme) :
Code : std::vector<iterator>::reverse_iterator it = v.rbegin();
Code : std::vector<bool>::size_type const n = v.size();
Code : typedef boost::result_of<functor(int)>::type r = functor(7);
Dans l'exemple de Pyramidev, un std::pair est utilisé mais l'utilisation d'un std::tuple, d'un boost::optional ou de n'importe qu'elle classe qui offrent les même services (ou équivalents) est légitime.le 24/09/2016 à 18:15 -
zobalMembre confirméSi c'est une blague, ça commence à être lourd.
Sinon, comme dit précédemment, le type est celui de la valeur d'initialisation.Code : 1
2
3
4
5
6
7
8
9
10
11
12int a = 4; auto x = a; // x est de type int float b = 3; auto y = b; // y est de type float vector<string> v {"texte1", "texte2"}; auto tab = v; // tab est de type vector<string> auto str = v.front(); // str est de type string auto iter = v.begin(); // iter est de type vector<string>::iterator auto f = [] (int n) { return n > 0; }; // f est de type function<bool(int)>
le 24/09/2016 à 18:42 -
JolyLoicRédacteur/ModérateurLa plupart du temps, j'essaye de trouver un nom qui définisse le rôle de la variable (password, plutôt que passwordString ou str). Mais il y a des cas où je n'y arrive pas (essayez de trouver un nom descriptif pour un itérateur!). Sans ce cas là, il y a homonymie non pas variable/type, mais plus variable/concept auquel répond le type.
Pour reprendre le cas de l'itérateur, je le nommerais plutôt it ou iterator que vector_of_string_iterator ou encore je nommerais une variable fileList même si son type est std::vector<std::string>.
D'ailleurs, à ce sujet, il y a eu des suggestions pour étendre les concepts à la déclaration de variables, histoire d'avoir un intermédiaire entre le type, trop précis, et auto, perçu par certains comme trop imprécis. On pourrait alors écrire Iterator it = v.begin();, le type de it serait déduit comme avec auto, mais ensuite, on vérifierait si ce type répond au concept Iterator, et si ce n'est pas le cas, on lèverait une erreur. Je ne sais pas trop si j'utiliserais une telle écriture si elle devenait disponible, ou si je resterais avec auto. Il faudrait que je l'expérimente dans la vraie vie.le 25/09/2016 à 22:39 -
BouskRédacteur/ModérateurMais auto n'est pas utilisable dans ce cas. Il n'a strictement rien à voir avec quelconque problème de performance, conso, poids du livrable, quelque soit le niveau ni rien. Ce n'est qu'un sucre syntaxique.le 26/09/2016 à 11:20
-
EhonnMembre chevronnéJe n'ai rien contre toi (je préfère le préciser
) mais j'ai une question sur un point spécifique :
À quel moment typedef boost::result_of<functor(int)>::type n'est pas aussi "magique" qu'auto ?
PS : @zobal
Note que vector<string>::iterator n'est pas un type vraiment/entièrement définit par la norme, on sait juste que ça respecte le "concept" de random access iterator (?)
Idem, pour les lambdas, le type de retour n'est pas définit (mais convertissible vers std::function).le 24/09/2016 à 21:57