À propos de WG21, Kona 2017

Quelques raccourcis :

Disclaimer

I wrote what follows mostly to keep my students informed of what a WG21 meeting is like, and I do not want to break the ISO code of conduct (I really don't want to do that!), but I do name people when I don't think it has any harmful effect (when discussions are more heated, I try to refrain from identifying individuals) as it might interest my students to see what kind of argument these bright individuals can formulate. Should you think it would be appropriate for me to remove things from this page, please tell me and I will proceed switfly.

Based on a recent (March 2017) clarification of the ISO code of conduct, I have anonymized all in-meeting discussions except for self-evident things like chairs asking for votes (it's an ongoing process, but I'll fully anonymize it as soon as I can).

Grâce à l'Université de Sherbrooke (en particulier, grâce à Jean Goulet et à Claude Cardinal du CeFTI) et au Collège Lionel-Groulx (en particulier grâce à Éric St-Jean), j'ai eu le privilège de participer à WG21, le comité de standardisation ISO du langage C++, qui est mon principal outil de travail et d'expression (outre la langue française elle-même). Il s'agit d'un truc prestigieux pour les informaticien(ne)s comme moi, et j'ai l'honneur de faire partie de ce comité depuis la fin de 2014.

Ce qui suit est une sorte de journal de voyage, avec éléments humains et éléments techniques. Ce ne sera probablement pas volumineux, car je serai là en tant que participant plus qu'en tant que « spectateur intéressé », mais j'essaierai de vous donner une idée de l'expérience.

Qu'est-ce que WG21?

Comme c'est souvent le cas dans les milieux scientifiques, le nom WG21 est peu spectaculaire. On parle ici du Working Group 21, soit le comité de standardisation du langage C++. Pour les informaticien(ne)s, c'est probablement ici que l'explication se suffit à elle-même, étant donné qu'on tombe directement dans leur créneau.

Pour la majorité d'entre vous, par contre, ça reste obscur, alors j'essaie une explication (il se peut que ça ne vous rejoigne pas, mais c'est de bon coeur) :

Le langage C++ existe depuis les années '80. Il a été standardisé par l'organisme ISO en 1998, puis solidifié en 2003 avec des ajustements (relativement mineurs) jugés nécessaires de par l'expérience concrète obtenue depuis C++ 98. Une révision très majeure du langage a été ratifiée en 2011, et C++ 11 est l'essentiel du langage par lequel nous exprimons nos idées aujourd'hui. Une révision mineure (mais fort appréciée) a été ratifiée relativement récemment (C++ 14), et la prochaine mise à jour majeure, C++ 17, est celle sur laquelle nous travaillerons à WG21 pour les prochaines années. Les objectifs de C++ 17 sont très ambitieux, et font saliver les gens qui, comme moi, cherchent à tirer le maximum de ce que ce langage a à offrir.

On me dit que nous sommes ≈300 membres de WG21 sur la planète, et qu'environ cent personnes se présentent aux rencontres du comité (les autres font surtout des contributions par écrit). Pour la rencontre documentée ici, nous serons environ 120.

Pour un peu de bagage supplémentaire sur l'événement, voir :

Pour les journaux de voyage d'autres participants, voir :

Pour des reportages plus « commerciaux » :

Début du contenu technique

Je vais mettre le contenu technique dans des blocs en relief, comme celui-ci. Si vous ça ne tombe pas dans vos cordes, passez par-dessus.

Sur le plan de la procédure, certains débats étant chauds et les gens qui débattent étant mes pairs, je vais m'abstenir de donner dans le nominatif dans ces sections (à moins que ça n'ait pas d'incidence).

Fin du contenu technique

Au préalable

J'ai toujours le coeur gros quand je quitte la maison pour une semaine ou plus, car je m'ennuie beaucoup de ma belle Za et de mes enfants (ce qui n'enlève rien à l'intérêt du travail que nous faisons lors des rencontres du WG21, qui sont passionnantes). Cette fois, je dois l'avouer, c'est pire qu'à l'habitude, et j'ai pensé annuler le voyage la veille du départ, car mon épouse que j'aime et moi avons vécu une épreuve qui aurait mérité que nous restions ensemble pour quelques jours.

Malheureusement, il était trop tard pour annuler le tout, et les conséquences financières auraient été désastreuses, alors je me suis résolu à partir malgré tout.

Jour -1 26 février 2017

Factoïde amusant : Dulles est un lieu dans un jeu de table (Les aventuriers du rail, en anglais Ticket to Ride) auquel nous jouons parfois en famille, et je me demandais où ça pouvait bien être, le nom ne me disant rien. Eh ben, Washington D.C., ça explique que le jeu y ait réservé une place!

Mon chic papa Réal a accepté de m'amener à l.'aéroport aux aurores, pour permettre à Za de se reposer (elle le méritait!). Ma mère Lucille a dépanné avec notre plus jeune, Ludo, lorsque les problèmes de la veille ont commencé, alors que Danielle et Jocelyn, les parents de mon épouse, ont pris en charge les deux plus jeunes (Vayda et Ludo) pour nous aider. À tous, d'immenses mercis. Vous êtes des amours, et nous apprécions sincèrement ce que vous faites pour nous et pour les enfants.

Le trajet pour aller à Kona passe de Montréal à Dulles (Washington D.C.), puis à Los Angeles, le tout avec des délais très courts pour passer d'un avion à l'autre, et mon départ de Montréal a été retardé pour cause de glace sur les ailes de l'avion. Le voyage a par contre été bref (et tumultueux; ça brassait!) et nous avons réussi à compenser (légèrement) pour le retard, ce qui m'a permis de ne pas manquer ma connexion vers Los Angeles. Sur ce vol, j'ai eu le temps d'écouter deux épisodes de CppCast, soit celui avec Matt Calabrese et celui avec Brittany Friedman (que je n'ai toutefois pas eu le temps de terminer, mais je poursuivrai dans mon prochain vol). J'aime bien apporter avec moi cette balado, qui est d'excellente qualité et dont le format sied à un voyage comme ceux que je suis appelé à faire (en plus, les animateurs et les participants sont de chics individus!). Pas de goûter (il y avait de la nourriture appétissante, mais je n'ai pas le budget requis), outre une petite galette au caramel vanillé, ma foi très agréable en bouche.

Les gens de l'aéroport Dulles ont été extrêmement gentils et accueillants; de plus, ils ont assurément le meilleur WiFi que j'ai rencontré dans un aéroport jusqu'ici. Bravo! Je prends le temps d'écrire un peu à ma belle Za, et je m'engouffre dans mon deuxième de trois vols aujourd'hui.


C'est un assez long trajet que celui de Dulles à Los Angeles, soit cinq heures et il fait relative et il fait relativement chaud dans l'habitacle. Étant mal assis, j'ai sommeillé un peu, sans plus, mais je me suis fait le plaisir d'écouter La soirée est encore jeune de la veille, en balado (j'ai ri à pleurer; c'était hilarant). Je termine aussi la balado avec Brittany Friedman puis j'écoute celle avec Marshall Clow, un individu extrêmement gentil et fort pertinent, suivi de celle avec Vinnie Falco. Avis à mes étudiant(e)s et à mes collègues : ces balados valent la peine d'être écoutées si vous souhaitez mieux comprendre ce que nos faisons lors d'une rencontre du comité de standardisation. Sur ce vol encore, pas de goûter, outre un sac de mini pretzels.

Seul truc amusant à savoir, vraiment : il y avait un Shih Tzu sur mon vol, dans les bras de sa maîtresse. J'ai pensé à Za qui aime tellement ces chiens au visage écrasé...


Arrivé à Los Angeles, après les délais pour nous permettre de sortir de l'avion, il me restait dix minutes pour me rendre au point d'embarquement de mon dernier avion de la journée. J'ai été chanceux ici encore du fait que l'avion avait un très léger retard (cinq minutes), mais ça m'a permis d'aller au petit coin et de ramasser un bagel canelle et raisins (seule chose au prix pas-trop-déraisonnable à proximité; à peine 2,5 USD... Un sandwich au thon tout simple, c'est quand même 9 USD).

Nous sommes quelques membres du WG21 sur le vol : outre moi-même, j'ai vu Matthias Gaunard, J. Daniel Garcia, Botond Ballo et quelques autres dont le nom m'échappe pour le moment. On bavarde brièvement avant d'embarquer pour réduire les frais de taxi en arrivant. J'ai à peine le temps de saluer ma belle Za avant de m'engouffrer dans l'avion.

Le lien WiFi de l'aéroport de Los Angeles est misérable, et ne me permet pas d'accéder à gmail pour collecter les documents que je souhaite lire pendant le vol (sécurité insuffisante). Heureusement, le toujours chic Botond Ballo a une copie archivée sur une puce USB et me la refile, ce qui me permettra d'être un peu plus efficace. Malheureusement, mon vol n'offre pas de prise de courant en classe économique, ce qui réduira ma productivité (moche, car c'est un vol de plus de six heures avec conditions météo de mauvaise qualité – ça brasse beaucoup à l'occasion, mais le pilote nous a prévenus d'office – alors j'aurais voulu profiter du temps au maximum). Botond Ballo me fait remarquer que le vol est plutôt vide (plein à je dirais, ce qui est inattendu étant donné que c'est la haute saison à Hawaii). Je poursuis les balados de CppCast : celle avec Stephan T. Lavavej, celle avec Alex Allain et celle avec Björn Fahller; enfin, je bascule à la musique une fois mes balados consommées.

J'aime bien normalement afficher les données de vol à l'écran apposé devant mon siège quand je fais un trajet comme celui-lci, mais notre vol a une autre particularité : il favorise un truc nommé DirecTV, qui permet de regarder la télé américaine pendant un trajet, or cela (a) ne m'intéresse pas beaucoup, et (b) ne fonctionne pas de toute manière une fois au-dessus du Pacifique, donc à peu près vingt minutes après avoir quitté Los Angeles (le voyage entre Los Angeles et Kona se passe à plus de au-dessus de l'océan : l'aéroport de Los Angeles donne directement sur le Pacifique, Kona est une île, et on ne survole pas la terre ferme entre les deux. Conséquence : on a le choix entre payer 8 USD pour regarder un film « surprise » qui tourne en boucle et ne pas payer ce prix et se faire imposer six heures de publicité sur DirecTV et ses vertus. Eh ben.


Nous nous posons à Kona, après avoir rempli les petites cartes affirmant que nous n'avons rien apporté qui pourrait nuire à l'écosystème local. Le pilote nous invite à faire profiter le commerce local et nous dit que nous sommes arrivés sur God's Gift to the World, rien de moins. Faut dire que c'est effectivement un très bel endroit.

Une fois arrivé à l'aéroport de Kona, la question est de savoir si mes bagages m'ont suivi malgré les courts transits... et la réponse est oui (ouf!). Matthias Gaunard a loué une voiture compacte et nous offre de nous amener à l'hôtel, mais nous sommes quatre (moi, J. Daniel Garcia, Botond Ballo et un autre dont le nom m'échappe mais qui arrive de Londres) avec bagages alors nous nous séparons un taxi. Sur la route, on échange des banalités sympathiques sur la durée du voyage (Botond Ballo vient de Toronto et a eu un voyage d'une longueur semblable à celle de mon propre voyage; J. Daniel Garcia arrive d'Espagne en passant par l'Allemagne pour faire une ligne directe de cet endroit vers Los Angeles, ce qui est très long). J'en profite pour parler météo avec le chauffeur : ici, tout le monde vit et travaille à l'extérieur, mais la météo annoncée parle de pluie cette semaine. Le chauffeur me dit qu'il pleut ici, mais jamais très longtemps, alors ça ne dérange pas les gens.

Contrairement à mon passage précédent, je ne suis pas dans le même bâtiment que celui où se tiennent la plupart de nos activités (le complexe hôtelier comprend trois tours), mais on parle de 15 secondes de marche au bord de la mer entre les deux, rien de grave. J'avais oublié qu'il y a des torches allumées un peu partout ici le soir, c'est joli. Bon accueil, température chaude (pour moi) mais agréable avec le vent et l'odeur de la mer.

Il est presque 22 h quand nous arrivons à l'hôtel. Je pars à la recherche du code de l'événement pour le WiFi (je l'ai reçu par courriel, mais sans accès Internet, pas facile de le retrouver). Je trouve un petit groupe de collègues qui discutent autour d'une bière (ça parle fort, en particulier entre Louis Dionne et John Lakos, qui discutent de comportement indéfini et de gestion d'erreurs en situation de bris de contrat). Andrew Pardoe me refile le mot de passe; pendant ce temps, une serveuse les informe que c'est le « Last Call », j'en profite pour prendre une bière à rapporter à ma chambre (question de retomber sur mes pattes). John Lakos paie la tournée et m'inclut dans le lot, ce pour quoi je le remercie.

Enfin à ma chambre, petite mais convenable (je suis seul; la dernière fois, j'avais une chambre qui aurait pu loger quelqu'un d'autre, c'était gênant). Je salue Za qui me répond (il esth du matin à la maison), je prends ma bière (les bières locales sont très bonnes ici) et c'est l'heure de dormir un peu.

Jour 0 27 février 2017

J'ai mis mon réveil pourh, heure locale (h du matin à Montréal), car j'ai beaucoup à faire pour me préparer (je vais manquer de temps). Un peu comme la dernière fois, je suis « bloqué pour piratage » dû à mon utilisation d'Internet (trop d'onglets ouverts, la compagnie locale pense qu'on fait ds mauvais coups), ce que je règle par un coup de fil.

J'écoute la radio de Radio-Canada et, à l'émission Médium Large, je tombe sur ma chumette Eza Paventi qui a accueilli une famille syrienne et vient de tourner un documentaire sur l'intégration de ces nouveux arrivants. C'est une belle surprise!

J'ai voulu aller me chercher un café et une bouchée pour déjeuner, mais l'endroit où (de mémoire) je faisais cela lors de mon séjour précédent semble être devenu un restaurant avec déjeuner, mais du genre où il faut s'asseoir, pas du genre où l'on accroche quelque chose avant d'aller prendre une marche. C'est moins dans mon budget, disons (même si ça semble très bon), et j'ai beaucoup de boulot devant moi alors je préfère revenir à ma chambre et essayer le café fourni par l'hôtel (on verra bien). De toute manière, le café ne manquera pas durant la journée.

Remarquez la ligne raturée. C'est que Vicente J. Botet Escriba m'a demandé de présenter p0319r1, que je ne connais qu'en surface, alors que nous avions travaillé p0320r1 ensemble, et j'ai dit « oui » en pensait qu'il parlait de l'autre. Je vais donc devoir me documenter un peu...

En plus d'être en retard dans ma préparation (j'ai une bonne centaine d'articles à lire; j'en ai lu plusieurs hier et ce matin, mais « la pile est haute »), j'ai constaté que j'ai plusieurs trucs à présenter cette semaine, la plupart devant LEWG, soit :

Dans la plupart des cas, ce sont des documents proposés pour Issaquah, mais que ls délais ne nous avaient pas permis de traiter. Je vais aller voir Jeffrey Yasskin, qui dirige les travaux de LEWG, pour lui demander de me donner le temps de les relire pour me rafraîchir la mémoire, question de faire un bon travail. Je lui en glisse un mot, et il accepte gentiment de m'avertir un peu d'avance (c'est un jeune papa, alors je pense qu'il est sensible aux débordements de boulot et de vie courante).


La salle se remplit peu à peu, et les travaux débutent àh 30. Les nouveaux visages sont rares cette fois, mais c'est une rencontre qui se prête moins que d'autres à accueillir des nouveaux participants; l'objectif principal est de ficeler C++ 17, ce qui serait un immense pas en avant. On survole rapidement le code d'éthique, les règles comportementales d'usage, la procédure décisionnelle, et ainsi de suite, mais on a pour objectif de faire en sorte que la plénière soit brève car le boulot déborde de partout, alors on escamote la présentation individuelle durant la plénière.

On a dix pays représentés formellement ici cette semaine (États-Unis, Canada, Grande-Bretagne, Suisse, Russie, Espagne, Finlande, France, et il m'en manque deux). C'est important de tenir le compte car cela peut avoir un impact sur les votes, dû aux procédures d'un organisme comme ISO. Je suis sur les feuilles de présence officielles maintenant (contrairement à mes deux premières participations), étant officiellement membre du répertoire ISO, ce qui fait toujours un petit velours.

On procède à l'adoption d'une douzaine de WD pour démarrer les travaux de la semaine. Les gens ont l'occasion de se prononcer sur les rapports livrés par les éditeurs de ces documents, mais personne ne le fait. Detlef Vollmann mentionne qu'il manque un numéro de document pour celui sur les coroutines, mais Herb Sutter indique que c'est un bogue relié aux délais administratifs (le numéro a été demandé). Herb Sutter dit aussi aux éditeurs qu'une adaptation éditoriale doit être fait à tous les documents cette semaine pour fins de respect des règles en vigueur. John Spicer demande si cela affectera les numéros de clauses, en particulier pour les clauses du standard lui-même (un monstre de plus de 1500 pages, tout de même, auquel on trouve ds références partout dans le monde); Herb Sutter dit oui, désolé. Désormais, tout document ISO devra avoir des clauses 1, 2 et 3 avec un contenu très spécifique, et c'est comme ça, alors faut changer la numérotation de tous les documents pour la décaler (et, surtout, décaler les références aux documents en question). Morale de cette histoire : référer au standard par les noms de sections, pas par leurs numéros.

Les Working Group Chairs ont l'opportunité de s'exprimer :

Clark Nelson indique que son passage en tant que Chair de WG21 arrive à terme à la fin de 2017, et qu'il envisage la retraite. La porte est ouverte pour recevoir des candidatures pour le remplacer. John Spicer s'est offert, en tant que Chair ou que co-Chair. Il faudra aussi un secrétaire pour remplacer Jonathan Wakely à Toronto, car il deviendra papa.

Jens Maurer explique la mécanique de la semaine, la répartition des groupes de travail dans les pièces, l'attribution des projecteurs, etc. Il semble que la journée pour EWG et CWG commencera dans la grande salle pour fins de discussion regroupant les deux. Les sessions de soirée prévues sont mardi soir (19 h 30, SG7 – réflexivité) et jeudi soir (direction général du langage); il se peut qu'il y en ait une pour SG14, mais Michael Wong n'est pas convaincu que ce soit présent.

Walter E. Brown demande aux gens qui tiennent à jour les divers Wiki d'essayer d'indiquer « ce qui s'en vient » pour faciliter la planification du temps.

On arrête àh 5, pour dix minutes (question de laisser les gens se déplacer). Je reste dans la grande salle pour les travaux de CWG.

Ville Voutilainen dirige les travaux de ce groupe de travail conjoint. On a plusieurs NB Comments qui demandent une décision commune des deux groupes.

US24 ne semble pas accompagné d'une proposition écrite. Le consensus semble être que l'idée est intéressante mais qu'il est trop tard pour procéder sans proposition sur la table. Rejeté faute de consensus

Laisser les implémenteurs d'apposer constexpr si cela semble approprié à leurs yeux est mis de côté, car l'impact est trop gros pour être considéré cette semaine (cela dit, on y revient plus tard ce matin; voir les discussions sur GB28)

Certains souhaitent renommer Structured Bindings, par exemple par Decomposition Declarations. C'est un débat de sémantique, vraiment, et il est tard pour renommer un tel mécanisme, comme le rappelle quelqu'un (après tout, les gens ont commencé à utiliser le nom sur les réseaux sociaux). Richard Smith pense que les deux termes ont leur place : un pour le mécanisme, et un pour ce qu'on en fait; il indique que le nom « public » du mécanisme peut demeurer Structured Bindings, et que l'on peut y aller de plus de précision dans le texte normatif. Quelqu'un demande pourquoi ne pas simplement renommer Decomposition Declarations vers Structured Binding Declarations. Quelqu'un pousse dans cette direction, qui semble pouvoir minimiser les irritants. Quelqu'un soulève une question importante sur la nomenclature des messages d'erreurs que soulèveront les compilateurs, souhaitant éviter la confusion. Quelqu'un revient sur le besoin d'avoir deux noms pour deux mécanismes, et dit ne pas voir le problème. On échange sur le besoin d'un nom dans certains cas. Quelqu'un est d'avis que CWG devrait choisir le nom dans le texte normatif. Un participant mentionne que le mot « déclaration » peut nuire dans le futur car certaines propositions sur la table peuvent mener à la matérialisation d'un objet en l'absence d'une déclaration. Quelqu'un pense que Structured Bindings devrait être le Term of Art pour les objets introduits par une Decomposition Declaration. Ville Voutilainen prépare un vote indicatif :

Quelqu'un demande s'il y a lieu de prendre un vote pour le statu quo, à titre indicatif. Ville Voutilainen dit que le statu quo tient si nous n'approuvons pas de changement. Quelqu'un rappelle que nous essayons de nommer deux choses distinctes par un seul nom. Dans la phrase suivante :

auto [a,b] = f();

... la déclaration entière serait selon lui une Decomposition Declaration alors que a et b seraient des Structured Bindings (pour le moment, a et b sont simplement des identifiers, ce qui est vague et d'une utilité discutable).

Brève pause dans les travaux, le temps de remplir nos tasses de café. Il est 10 h. Certains dans la salle trouvent ces débats terminologiques inutiles, mais c'est bien sûr le coeur des travaux d'un groupe tel que CWG, et pour ces gens, un nom inapproprié est un frein à la productivité. Choc des cultures, je présume. Je me sers un café, Gor Nishanov passe dire bonjour (quel individu adorable!), on discute informellement ici et là, et on recommence.

GB28 porte sur constexpr dans la bibliothèque. Quelqu'un explique que noexcept a été appliqué de manière sélective par les implémenteurs avant de devenir obligatoire, et pense que constexpr pourrait avoir droit au même traitement, mais pour le moment les deux sont traités différemment (liberté pour noexcept, contrainte pour constexpr). Quelqu'un questionne la portabilité, pour le code client, des résultats de cette expérimentation (c'est « hautement détectable »). Quelqu'un retrace l'historique des échanges à ce sujet. Quelqu'un rappelle que noexcept est maintenant aussi « hautement détectable », dû à nos changements les plus récents, et ne voit pas cela comme un obstacle. Quelqu'un signale que ceci peut causer des violations d'ODR et influencer le lieu de l'initialisation des variables. Quelqu'un y voit un risque de fuite dans l'ABI d'une implémentation, mais ne pense pas que ce soit dramatique. Quelqu'un rappelle que les bibliothèques ne sont déjà pas ABI-compatibles entre elles. Quelqu'un y voit un lieu fécond pour ouvrir la compétition entre les implémentations. Quelqu'un distingue les implémenteurs de bibliothèques standards et les individus chargés de leur entretien; il craint l'impact de ce changement pour le second groupe, et pense qu'il deviendra rapidement difficile pour un programme C++ de migrer d'une bibliothèque à l'autre. Certains discutent de la possibilité d'accepter ou non les extensions à constexpr. Quelqu'un se dit d'avis qu'il est un peu tard pour aborder une question de cette importance. Quelqu'un suggère qu'on peut ne rien faire tout simplement, car les compilateurs sont ici tout à fait dans le domaine des extensions et peuvent faire comme ils le font avec d'autres extensions aujourd'hui. Quelqu'un indique qu'il est difficile d'ajouter constexpr à la bibliotheque standard sans expérimentation préalable, ce qui le rend favorable à cette ouverture.

On vote, et le consensus semble être que ça ne passe pas. Quelqu'un suggère que l'on reprenne la réflexion au début des travaux pour C++ 20.

On aborde ensuite la question des Deduction Guides. L'auteur original de cette proposition prend le plancher. Le pauvre est en béquilles alors on l'aide à transporter son matériel. Il s'assied, dû aux circonstances, et présente les fruits de sa période d'expérimentation. Il explique avoir expérimenté avec plus de 100 classes et avoir reçu beaucoup de critiques constructives. Dans le cas des guides implicites, quelqu'un dit que plus de des classs évaluées se sont comportées exactement comment on aurait plus le souhaiter. Pour les autres, il a fallu suppléer des guides explicites pour combler certains manques des guides implicites (surtout dans le cas des constructeurs de copie et de mouvement). Il mentionne vector qui a demandé trois retouches, pour tenir compte aussi du constructeur de séquence. Les programmes dépendant beaucoup de métaprogrammation ont été les plus susceptibles d'avoir besoin de guides explicites.

Quelqu'un dit que le recours le plus récurrent aux guides explicites est pour forcer la décrépitude (Decay) des types, surtout pour les références. Il mentionne en particulier std::pair<const T&,const T&> dans le cas où T est un tableau. Certains constructeur utiles comme le constructeur de séquence ne seront pas déductibles implicitement à partir du contexte, comme le cas vector(It,It) qui doit générer un vector<typename iterator_traits<It>::value_type>. La question des allocateurs a aussi demandé un peu de soins, de même que le cas shared_ptr(T*) qui déduit implicitement un non-tableau. De manière un peu surprenante, = delete n'a pas été nécessaire, outre un cas limite. Cependant, quelqu'un est d'avis que = delete serait utile pour les guides implicites des types unique_ptr et shared_ptr (bien qu'il y ait des voies de contournement; ce serait un atout, pas un requis). Quelqu'un constate que les règles existantes permettent de masquer le constructeur de copie dans des contextes où il aurait été à privilégier, et pense que l'ordre de certaines règles devrait être revu pour placer le guide de déduction plus bas dans les cas à considérer. Il estime que les guides implicites sont une bonne chose, dans l'ensemble. Quelqu'un trace un lien avec Java, qu'il utilise au quotidien : le langage est si verbeux et demande tant d'écriture de la part ds programmeuses et des programmeurs que lui et ses collègues tendent à privilégier des générateurs de code; sa perception est que les Deduction Guides, surtout ceux implicites, réduisent beaucoup la répétition inutile de code (le Boilerplate Code).

Quelqu'un prend le relais et dit qu'il était sceptique au préalable mais que son expérience est plutôt positive dans l'ensemble.

Ville Voutilainen demande l'opinion de CWG. Le consensus semble être de ne pas prendre le temps de l'assemblée toute entière et de ramener cela à même le groupe de travail, pour fins de productivité.

Quelqu'un apporte un exemple :

tuple<int,int,int> x;
tuple a = x; // tuple<int,int,int>
tuple b(x); // tuple<int,int,int>
tuple c{x}; // tuple<int,int,int>?
tuple c2 = {x}; // tuple<int,int,int>?
auto d = tuple{ x }; // tuple<int,int,int> ou tuple<tuple<int,int,int>>?
tuple e({x});
list y{ ... };
reversed(reversed(y)); // avec des reverse_iterator

On a des échanges sur la cohérence de nos énoncés. On souhaite une initialisation uniforme, après tout, malgré la tare de vector<int> où les accolades et les parenthèses entraînent des initialisations distinctes. Certains poussent pour que le sens de c et d soit uniforme. Quelqu'un parle de la difficulté de comprendre les intentions à partir du code dans le cas d'un tuple, et pense que d ne devrait pas donner un tuple<tuple<...>> (dans un tel cas, selon lui, mieux vaut laisser le code client expliciter son intention).

Quelqu'un mentionne que dans un cas où il existe plusieurs surcharges à l'initialisation, nous avons des mécanismes qui fonctionnent; il ne souhaite pas un remède qui soit pire que la maladie, et il n'est pas convaincu que les Deduction Guides éliminent la totalité des fabriques. Quelqu'un mentionne l'ambiguité du mot « simple » (ici, {1} et {1,2,3} mèneraient à des déductions distinctes). Quelqu'un mentionne qu'il serait à l'aise d'expliciter tuple dans les cas complexes. Quelqu'un parle de pratique préexistante et mentionne future, où nous cherchons à déballer les future<future<T>> pour fins d'enchaînement dans des continuations. Quelqu'un mentionne d'autres cas de « types emballés », en particulier les intervalles. Quelqu'un dit que le déballage implicite, qui fait disparaître des types, peut surprendre et compliquer le débogage. Quelqu'un insiste sur l'importance d'un comportement homogène pour faciliter la programmation générique. Quelqu'un aimerait que le concepteur d'une bibliothèque ait le contrôle sur la forme (explicite ou implicite) du déballage qui se produira. Quelqu'un pense que nous avons ce contrôle : un guide explicite. Quelqu'un mentionne qu'un guide explicite changerait les comportements de a et b. Quelqu'un mentionne optional<T> qui est un cas connexe.

Quelqu'un se dit d'avis que les cas spéciaux, qui déballent implicitement, soient les cas particuliers, pas le cas général. Il n'aime pas l'effet de surprise qui vient avec une perte implicite de sémantique. Quelqu'un est d'accord dans la mesure où l'auteur d'une bibliothèque peut rendre ce comportement de déballage implicite si cela lui semble à propos. Quelqu'un pense que l'immense majorité des cas d'utilisation « ordinaires » ne sont pas des tuple<tuple<...>> ou des optional<optional<T>>, et recommande de ne pas modifier le comportement par défaut proposé.

Ville Voutilainen suggère que l'on aille manger, et que la décision se prenne cet après-midi avc EWG seulement. CWG se rencontrera en début d'après-midi pour discuter des modules. Il se peut que l'on se regroupe tous ensemble pour discuter de std::launder() par contre.

N'ayant ni temps, ni budget, je vais me chercher un sandwich du jour au Subways le plus près. Je croise Billy Baker, arrivé ce matin trente minutes avant la plénière car, bien qu'il habite aux États-Unis, les aléas du vol (un avion surchargé, des retards, des transferts imprévus) l'ont forcé à prendre cinq vols sur deux transporteurs distincts pour arriver jusqu'ici. Disons qu'il semble fatigué.

Une particularité de CWG est que la plupart des participants travaillent aussi pendant les pauses (je ne suis pas le seul à être débordé), ce qui fait que pendant le dîner, je partage la salle avec Mike Miller, Roger Orr et Jens Maurer.. Difficile de cacher le bruit constant du ventilateur de mon laptop sur-le-point-de-rendre-l'âme, ce pourqui je leur offre mes excuses. Disons que je suis chanceux qu'ils aient le sens de l'humour... et que je suis vraiment dû pour un nouvel appareil.

Pendant que la pièce se remplit, et que les collègues aux oreilles les plus sensibles s'éloignent de mon bruyant laptop, on échange un peu sur les travaux de WG23 auxquels je participe, et sur la perception de relative insécurité de C++ que peuvent avoir des individus qui n'ont du langage qu'une vision quelque peu... dépassée, disons. John Spicer se permet une boutade à l'effet que la plupart des programmes C++ qui meurent sont en fait des suicides, et on se bidonne un peu.

On commence les travaux.

D0583R0 – Modules: Contexts of Template Instantiations and Name Lookup

Quelqu'un prend le plancher et explique les efforts de clarification du propos.

Quelqu'un demande si la définition d'un template doit apparaître dans l'interface d'un module. Réponse affirmative.

Quelqu'un estime que les règles existantes doivent être enrichies pour faire le lien entre les pratiques existantes et leur application dans le contexte des modules. Quelqu'un mentionne avoir essayé de le faire, mais ne pas y arriver. Il dit avoir produit un exemple pour illustrer l'application des règles déjà présentes dans le texte du standard (exemple qu'il présente), mais ne pas avoir trouvé de « trou » dans les règles existantes. ADL lui a été d'un grand secours.

Quelqu'un mentionne les règles de P0500 qui, selon lui, pourraient être clarifiées dans le contexte de modules, ce qui pourrait réduire les préoccupations.

Quelqu'un met de l'avant un exemple concret :

module Z;
export struct Z {};
// ... module A
module A;
export template<ltypename X, typename Y, typename Z>
   void f(X x, Y y, Z z) {
      g(x);
      g(y);
      g(z);
   }
import Z;
void g(Z, int = 0);// ici, si le code client utilise f, dans lequel des modules cherche-t-on Z?

La question qui le préoccupe est de savoir dans lequel ds modules la fouille pour Z doit être faite. Quelqu'un ne souhaite pas que l'on fouille tous les modules possibles pour s'en sortir. Quelqu'un démontre le risque de générer des cycles dans les appels.

Une autre préoccupation que soulève quelqu'un est le cas où une fonction serait écrite pour s'appliquer sur un type défini dans un autre module. Il faut éviter que le type ne soit jamais trouvé. Ceci peut survenir dans le cas d'un namespace réparti dans plusieurs modules. Quelqu'un fait un parallèle avec la relation entre <iostream> et <iomanip>, où ce dernier est en pratique une sorte de complément au premier. Il faut une terminologie pour décrire ces règles. Quelqu'un dit avoir essayé d'exprimer cette idée avec les module partitions discutées à Issaquah, mais ne pas avoir eu le succès attendu. Quelqu'un exprime des craintes dans un cas où un même type est déclaré dans plusieurs en-têtes; à ses yeux, il n'est pas clair sur la base des règles existantes de savoir dans quel module fouiller pour en trouver la définition.

Quelqu'un propose un autre exemple :

module A;
export struct S {};
// ...
module B;
import A;
export f(S);
// ...
import A;

Quelqu'un décrit les règles implémentées dans son compilateur, et met de l'avant les cas où le Name Lookup seul ne suffit pas.

En fait, la plupart des gens ici s'entendent sur ce qui doit être fait, mais il ne semble pas y avoir d'accord sur la clarté de la spécification en ce sens. Quelqu'un trace un graphique sous forme tabulaire pour expliquer le contexte de visibilité des types selon les cas d'exposition et de consommation envisageables. Quelqu'un dit que les règls existantes parlent de contexte, de points d'instanciation; quelqu'un fait remarquer que les modules sont de multiples contextes, ce qui demande clarification à ses yeux.

Quelqu'un dit que dans un cas comme f(T&,U&), il faut débuter par le contexte d'instanciation; si on trouve le type recherché dans le namespace de T, c'est réglé. Idem pour le namespace de U. Les ambiguïtés possibles sont les mêmes qu'à l'époque pré-modules.

Quelqu'un suggère le cas où H.h déclare struct Z, module A inclut H.h et définit f(Z), et le code client inclut H.h, définit sa propre version de f(Z) puis importe l'interface de A. Y a-t-il conflit?

Autre exemple :

// T.h
struct T { };
T operator+(T,T);
// ...
#include "T.h"
import F;
module M;
void g(T t) {
   T t;
   f(t);
}
// ...
module F;
export template<class T> void f(T x) { x + x; }

Quelqu'un pense qu'on devrait s'abord s'assurer que le cas non-template soit bien compris d'abord. Dans l'exemple ci-dessus, la terminologie semble fonctionner. Quelqu'un mentionne par contre qu'une partie du travail est réalisé dans une autre unité de traduction; c'est à son avis la visibilité dans cette autre unité de traduction qui est obscure. L'exemple ci-dessus fonctionne, cela dit.

Quelqu'un ramène l'idée de namespace partitions, qui traçait des « liens moraux » entre fonctions et types associés mais logés dans des unités de traduction disjointes.

Quelqu'un essaie de paraphraser sa compréhension de la vision véhiculée par le texte. Un accord s'installe quant aux termes tels que paraphrasés. On convient qu'il faudrait ramener le concept de namespace partition mais le lier plus efficacement aux règles de déduction d'ADL.

Une discussion s'ensuit à propos du cas où un même type « global » (pris d'un fichier d'en-tête) est défini dans plusieurs fichiers. Traditionnellement, le modèle lexical rend illégale une double définition d'un même type dans une même unité de traduction. Un exemple suit :

module M X.h module N
#include "X.h"
// ce qui précède «module» est
// dans le «module global»
namespace Q {
   X operator+(X,X);
}
module M;
export template <class T>
   void g(T obj) {
      return obj + Q::X();
   }
void j(Q::X x) {
   g(x);
}
namespace Q {
   struct X{};
}
#include "X.h"
module N;
import M;
void h(Q::X x) {
   g(x);
}

Ceci fait embarquer ADL pour la peine. Quelqu'un est d'avis qu'on ne trouve pas l'opérateur + ici sur la base du texte existant.On échange sur la question de savoir si c'est un bogue dans la spécification, ou s'il s'agit d'une acte malicieux (auto-malicieux?) de la part de la programmeuse ou du programmeur pour cacher un nom. Quelqu'un est d'avis que le texte reflète l'intention dans ce cas : l'erreur de desing à ses yeux tient au non-groupement des opérations sur un type avec ce type.

Quelqu'un demande si l'interaction entre le « monde traditionnel » des en-têtes et le « nouveau monde » des modules est la source des difficultés. Quelqu'un dit que les deux vont interagir en pratique, et ce pour longtemps, donc que les deux doivent fonctionner ensemble, par design. Il se dit d'avis que l'exemple sous discussion est excellent pour faire la démonstration de pratiques saines ou malsaines de programmation. Quelqu'un dit que l'opérateur + devrait en fait être un détail d'implémentation dans ce cas-ci (ça devrait s'appeler g_impl()). Gabriel Dos Reis montre comment il devient important de ne pas rendre les détails d'implémentation visibles par voie d'ADL.

On en est rendus à :

// X.h
namespace Q {
   struct X { };
}
// ...
#include "X.h" // (global module)
namespace Q {
  X operator +(X,X); // private implementation detail
}
module M1;
export template<class T>
   void g(T t) { t + Q::X(); } // takes X from this TU and from the M2 TU
void j(Q::X x) {
  g(x);    // ok
}
// ...
#include "X.h" // global module
module M2;
import M1;
void h(Q::X x) {
  g(x);    // ill-formed, can't find operator+
}

Quelqu'un propose un autre exemple :

module A;
export template <class T>
   void f(T t) {
      return t + t;
   }
// ...
module B;
import A;
export template <class T>
   void g(T t) {
      f(t);
   }
// ...
struct S {};
S operator+(S, S);
module C;
import B;
export template <class T>
   void h(T t) {
      g( (t, S()) ); // opérateur virgule, sans commentaire
   }
// ...
import C;
void i() {
   h(0);
}

Je ne commenterai pas le recours à l'opérateur , dans l'appel à g() dans le module C, sauf pour dire que Quelqu'un sort tout droit des profondeurs de l'enfer  . On convient tous que traditionnellement, ceci fonctionnerait à partir de fichiers d'en-tête car le contexte d'instanciation de f(T) serait la ligne juste avant la fonction i(), mais dans ce cas-ci, le contexte d'instanciation de f(T) est le module B. Le problème semble être la mémoire que le compilateur doit avoir des multiples unités de traduction impliquées dans la navigation d'un appel de fonction...

On prend une brève pause vers 15 h. Les discussions se poursuivent.

Quelqu'un revient d'une séance avec EWG où les discussions ont porté sur la possible suppression de l'une des règles associées à std::launder() lorsqu'un objet existant est remplacé par un autre objet du même type par voie de Placement New, alors qu'un pointeur menait sur l'objet a priori, pour déterminer la validiité d'accéder au nouvel objet à travers l'ancien pointeur (à savoir : doit-on passer par std::launder() ou non dans un tel cas?).

Il semble que le consensus n'ait pas été atteint.

On se repose un peu, dix minutes, puis Hubert Tong parle d'un cas qu'il a rencontré où un type pourrait avoir en même temps une taille nulle et non-nulle. On se bidonne un peu, mais c'est de la terminologie pas tout-à-fait simple.

Quelqu'un reprend la parole et cherche à clarifier sa pensée quant à la provenance d'un mot apparaissant dans le module global. Quelqu'un dit que dans le plus récent exemple discuté, il pense que le lookup est fait dans le module C, ce qui demande de retracer le nom global S du point où il a été défini. Pour tous les modules autres que le module global, il n'y a pas de besoin de réaliser une telle trace; le problème survient strictement dans le module global. Quelqu'un est d'accord; on veut que le code existant fonctionne, et c'est une conséquence.

Quelqu'un demande pourquoi cette trace est requise; quelqu'un rappelle que dans l'exemple dont on parle, C::S n'est pas directement visible de D. Quelqu'un pense qu'on peut modéliser la séance de points d'instanciation possibles, pour fins de visibilité, de manière linéaire. Quelqu'un demande si les règles sont les mêmes dans le cas où le module est explicitement nommé, mais quelqu'un pense que ça peut être un cas à part. Pour le moment,§14.6.4.1 [temp.point] donne les règles actuelles. On devrait pouvoir rediscuter de tout cela mercredi.

Coroutines

Quelqu'un dit que Gor Nishanov a fait les changements demandés. Il souhaite savoir si nous le faisons revenir pour en parler ou si on détermine que le document, incluant ces modifications, est prêt pour un vote le menant au statut de PDTS pour vendredi.

Quelqu'un pense qu'il serait sage de le revoir, entre autres pour discuter du passage de paramètres (par copie) et de la possibilité de réaliser Copy Elision, deux éléments techniques qui, selon lui, ne sont pas nécessairement clairs dans le texte proposé. On le contactera donc.

CH2 – volatile

Quelqu'un ìndique que cette question temrinologique a été discutée lors de téléconférences préalables. On y jette un bref coup d'oeil, puis on convient qu'il y a lieu de le présenter vendredi.

P0488R0

On pense le porter pour un vote vendredi.

GB29

Quelqu'un voit ceci comme un changement de terminologie, pas comme un changement normatif. Il pense que les gens souhaitent une manière homogène de faire de la taille une propriété des types, pour dire « an object occupies n bytes », ce qui ne veut pas dire la même chose que « an object owns n bytes ». Les bits de padding jouent ici dans le choix des mots, et il faut tenir compte du padding interne au type (incluant la partie parent) dans l'écriture.

Quelqu'un fait aussi remarquer que dans le cas où un objet contient du padding, sa zero-intialization peut ne pas remplir tous les bits du substrat avec des zéros.

GB15

Quelqu'un pense qu'il serait sage de l'examiner cette semaine en vue de C++ 17, car elle a un impact normatif. Il propose le texte qui résoudrait Core Issue 2011. Unclear effect of reference capture of reference. En effet, le texte existant laisse entendre la possibilité de capturer une référence par référence, ce qui n'a pas vraiment de sens.

On pense le porter pour un vote vendredi.

GB66

Celle-ci est reliée au remplacement d'operator delete(void*,size_t) qui devrait être accompagnée d'un remplacement d'operator delete(void*) par conformité. Quelqu'un va essayer d'écrire quelque chose.

GB68

Quelqu'un rappelle que celle-ci, à propos d'un usage inapproprié du nom Literal Type, a été discutée à Issaquah. Quelqu'un s'en occupe.

JJP3

Quelqu'un pense que c'est un changement éditorial. Quelqu'un pense que c'est un cas où nous souhaitions explorer une terminologie alternative. Les notes sur le Wiki d'Issaquah ne sont pas claires (c'est peut-être ma faute), d'indiquant pas les raisons. On parle d'un Placement New sur un objet en mémoire statique ici.

Quelqu'un se demande si la création d'un objet en mémoire statique impacte le choix de mots ici. Quelqu'un dit que la création dynamique d'un objet peut mener à un appel au destructeur statique. Quelqu'un pense que le sens donné au mot object dans cette section, soit « an object is a region of storage », est le sens antérieur à C++ 17.

Quelqu'un demande si le qualification non-allocating peut être appliqué au Placement New dans ce contexte. Quelqu'un dit que c'est une terminologie non-normative, mais Quelqu'un pense que ça peut suffire. §5.3.4 p. 16 parle de « If the allocation function is a non-allocating form (§18.6.2.3)... »

Quelqu'un demande si operator new retourne un objet ou un espace d'entreposage. Quelqu'un pense qu'on parle d'un espace d'entreposage, qui délimite la durée de vie qu'on y placera.

On accepte JP3 tel quel, outre des retouches éditoriales. Quelqu'un mentionne que le pointeur retourné peut ne pas être sécuritaire; Quelqu'un ne se sent pas terriblement préoccupé. On peut le passer comme un changement éditorial, pas besoin d'un vote.

CA12

Cette demande tient à clarifier la situation dans un cas comme celui-ci :

#include <new>
int bar() {
   alignas(int) unsigned char space[sizeof(int)];
   int *pi = new (static_cast<void *>(space)) int;
   *pi = 42;
   return [=]() mutable { 
      return *std::launder(reinterpret_cast<int *>(space));
   }();
}

Quelqu'un fait remarquer que le tableau capturé n'est pas nécessairement bien aligné pour le type qui y a été déposé. Devrait-on copier l'alignement d'origine? On pense que oui.

Quelqu'un demande si on a le droit de faire ce changement dans les circonstances, car c'est un bogue (obscur!) qu'on vient de découvrir. Quelqu'un indique que ça va nous exploser au visage avec les Structured Bindings aussi; cela dit, on réglera ça pour C++ 20, car c'est un bogue qui remonte à C++ 11.

Quelqu'un demande si std::launder() est utile ici. Quelqu'un dit que si, en particulier si on enlève la λ, car reinterpret_cast ne s'applique qu'à des types qui sont pointer-interconvertible. Quelqu'un mentionne que le bit_cast qui s'annonce va nous aider, en particulier dans le cas de la « lecture d'objets » sur un lien réseau; dans ce cas bien précis, un bit_cast est une approche plus pertinente qu'une danse faite de std::launder() et d'un reinterpret_cast.

Quelqu'un pense que faire fonctionner ce cas est important pour d'autres situations, en particulier optional<T>. On convient d'en faire un cas à part entière.

Quelqu'un remarque que le standard contient au moins trois descriptions distinctes des règles de copie d'un tableau (capture dans une λ Structured Bindings; membres d'un objet). Faudrait en profiter pour ramener ça à un seul cas.

Reformulation de la section [expr.prim.lambda]

Quelqu'un explique que cette nouvelle section fait surtout du déplacement de texte, mais est suffisamment différente de l'originale pour mériter notre attention.

Ça nous convient. Il y a quelques exemples adorables là-dedans.

lia-idee.pdf

Les références de §1.2 [intro] ont été mises à jour, et permettent de définir certains termes qui étaient utilisés sans être définis auparavant.

La clause ajustée est dans la section du standard « appartenant » à CWG, mais il serait sage de consulter LWG aussi puisque ça les touche.

Quelqu'un fait remarquer que l'une des références est incomplète (il manque une date).

Il est 17 h ici, et ce fut une grosse journée alors nous fermons les livres sur les travaux de CWG jusqu'à demain matin,h, ou plutôt juste après les discussions sur les concepts chez EWG, car cette discussion implique plusieurs personnes ici et on parle d'un sujet d'intérêt général pour le comité dans son ensemble.

Je suis revenu à ma chambre pour parler un peu à mon amoureuse Za et à ma grande Marguerite, suite à quoi je suis allé me chercher une salade de papaye au resto Thaï non loin. Sur le chemin, j'ai croisé Michael Wong avec qui j'ai bavardé un peu (quel chic type, vraiment!). On nous a arrêtés pour nous poser des questions sur SG14, et j'ai eu droit à des félicitations pour mes travaux sur les exceptions des deux dernières années (ça fait drôle de se faire reconnaître par des inconnus). Au retour à ma chambre, j'ai parlé un peu à nouveau à Za, mangé ma salade, lu quelques trucs (la pile de trucs à lire demeure très haute) et je suis allé me coucher... Il n'est pas encore 20 h, heure locale.

Jour 1 28 février 2017

Je me suis levé versh 30 car ma belle Za avait un rendez-vous médical auquel je voulais participer (de mon mieux) à distance (vive Skype dans ces moments!), et nous avons tout de même cinq heures de décalage horaire l'un avec l'autre. Pour les curieuses et les curieux, les nouvelles étaient encourageantes, mais le stress pré-voyage n'est pas encore derrière nous et je me sens bien loin des miens.

Douche, café (celui de la chambre est correct; en général, le café à Hawaii est excellent par contre, et beaucoup moins cher que le café hawaïen auquel nous avons accès au Québec), puis beaucoup de lecture car j'ai un retard fou sur ce plan. Ce matin, CWG ne se réunira pas àh car EWG discutera des concepts, l'un ds plus importants sujets dans le monde de C++ depuis des années, et de gros noms présentent des designs compétiteurs. Comprendre les enjeux (personne dans ce dossier n'est bête, en fait c'est tout le contraire) demande du temps et beaucoup d'attention, mais j'ai littéralement des centaines de textes à lire, et ils ne sont pas simples.

Sans surprises, bien que j'en aie lu beaucoup, je n'ai pas épuisé la liste des textes sur les concepts au moment de mon arrivée dans la salle où se tiennent les rencontres d'EWG, versh 45. Courte discussion amicale avec l'ami Walter E. Brown, toujours aussi charmant. L'atmosphère est fébrile ce matin.

Hier, bien que je ne l'aie pas indiqué, j'avais un peu de difficulté à lire les projections sur le grand écran de la salle de réunion. Je pense que c'était une combinaison d'un projecteur de qualité insuffisante pour cette salle et d'une légère baisse de la qualité de ma vue à longue distance. Triste, mais je vieillis, manifestement. Ce matin, je me suis assis un peu plus près (au centre de la salle plutôt que derrière), et le projecteur semble de meilleure qualité, ce qui me permet de tout voir beaucoup plus clairement.

Quand tous les principaux acteurs pour l'enjeu clé du matin sont arrivés, les travaux se mettent en branle. Herb Sutter recommande aux gens de centrer leurs arguments sur des bases objectives (rétroaction d'usagers, expérimentation, ce genre de truc) pour éviter des dérapages.

On hésite entre faire débuter les présentations par Bjarne Stroustrup ou Richard Smith, qui amènent des visions différentes à la discussion; c'est à Bjarne Stroustrup que revient l'honneur en fin de compte. Sa proposition est P0557R0.

P0557R0 – The Future of Generic Programming

Bjarne Stroustrup trace un historique des travaux sur les concepts, depuis 1987. Les objectifs clés sont les mêmes depuis le début : interfaces à coût nul, bien spécifiées, et expressivité maximale. Une partie des objectifs est atteinte déjà par les templates (Turing-Complete, plus rapides que le code écrit à la main), mais nos interfaces mènent à des messages d'erreurs beaucoup trop complexes. Plusieurs jalons dans l'avènement des concepts au fil des ans sont présentés, jusqu'à leur implémentation dans g++ pour fins d'expérimentation.

Bjarne Stroustrup montre comment la programmation générique peut devenir aussi simple que... la programmation tout court. Les templates ne permettent pas tout à fait cette simplicité, malgré leurs atouts. Les concepts sont des prédicats statiques sur un ou plusieurs types, vraiment.

Bjarne Stroustrup montre pour quelle raison il souhaite une notation concise, permettant des choses telles que void f(Sortable&); plutôt que template<class T> requires Sortable<T> void sort(T&); ou que template<Sortable T> void sort(T&); (car c'est un sujet de débat; cette forme mène à des irritants et à de la confusion dans certains cas). Il décrit ensuite les deux formes traditionnellement proposées de concepts, soit la forme « variable » et la forme « fonction ».

Bjarne Stroustrup suit avec un argumentaire en faveur d'une saine définition de concepts, soit s'astreindre à ne définir des concepts que lorsque ceux-ci décrivent une sémantique. En ce sens, Integral<T> est approprié à ses yeux, mais Incrementable<T> ne l'est pas.

Une discussion de requires requires... suit; cette séquence de jetons apparaît parfois avec l'acception des concepts dans la TS existante. Quelqu'un est d'accord sur le fait que c'est un passage perfectible, mais ne voit pas cela comme un obstacle insurmontable. La possibilté de surcharger les concepts est aussi discutée. Un plaidoyer pour le passage aux concepts s'ensuit, pour réduire le recours à des trucs comme enable_if et améliorer, dans l'ensemble, l'expérience de programmation.

Quelqu'un parle ensuite du Definition Checking, un dossier chaud car extrêmement complexe sur le plan du calcul. Il suggère de ne pas s'occuper de ce dossier dans l'immédiat, car trop de questions ouvertes demeurent.

Quelqu'un liste plusieurs exemples d'utilisation, puis décrit des espaces qu'il entrevoit pour améliorer le mécanisme tel que proposé : supprimer le mot bool dans les concepts, car ceux-ci sont toujours bool de toute manière; permettre d'ajouter des Expression Concepts; clarifier le sens de f(Iterator,Iterator) qui actuellement est différent de f(auto,auto) (le premier exige le même type aux deux endroits, mais pas le second).

Plusieurs estiment que nous devrions accepter les concepts dès C++ 17. À son avis, ils sont prêts.

Quelqu'un demande s'il est opportun de poser des questions techniques; on convient que oui, mais tant qu'on reste sur le fond du débat. Quelqu'un se demande si, en expérimentant avec les concepts, apposer un concept trop restrictif sur les paramètres d'une fonction bloquera le code client qui cherchera à l'utiliser, et quelqu'un confirme que c'est le cas, sans égard à la définition de la fonction. C'est une bonne chose, en fait; bien mieux qu'une erreur à l'exécution. Quelqu'un trace un lien avec les contrats, qui son l'un des ses sujets d'intérêt personnels.

P0587R0 – Concepts Revisited

Richard Smith présente sa réponse à la rétroaction de ses usagers sur la base de la TS sur les concepts. Il compte couvrir la syntaxe, l'équivalence entre concepts, le problème de l'ordonnancement partiel des concepts et la définition des fonctions génériques.

Pour ce qui est de la syntaxe, Richard Smith propose d'unifier les deux syntaxes existantes (variable et fonction) en une seule, et d'en faire un concept (!) de première classe du langage. Il estime que ce virage syntaxique allégerait leur utilisation, et réduirait les risques de surcharge accidentelle dans le cas de fonctions (Richard Smith propose d'unifier les syntaxes sur la base de la notation de variable). Quelqu'un signale que leur feedback usager n'a pas montré d'utilisation concrète de la surcharge de concepts. Quelqu'un est aussi d'avis qu'on pourrait aller dans cette direction. Quelqu'un a par contre des cas où ses concepts reposent sur des typedef assez lourds, et dit apprécier les fonctions pour cette raison. Quelqu'un dit vouloir les concepts, avec ou sans les ajustements, et souhaite qu'on garde les portes ouvertes. Quelqu'un se demande quelle est la raison pour souhaiter éliminer une des deux syntaxes; quelqu'un y voit plus de « contre » que de « pour », du fait que ça ne sert que peu en pratique et que ça crée des ambiguïtés.

Les équivalences sont un problème de fond, dont on discutait déjà à ma première participation au WG21 à Lenexa, en 2015 (et sans doute avant), soit le fait que deux concepts ne sont équivalents que s'il sont écrits exactement de la même manière, jeton pour jeton (donc template<class T> void f() requires T()==0&&true et  template<class T> void f() requires T()==0x00 sont distincts), et il y a une infinité de cas comme celui-ci (par exemple, (A&&B)&&C n'est pas équivalent à A&&(B&&C) dans une clause requires, et il en va de même pour typename T::template X<I> et typename T::template X<I+0>). Ceci implique que reformuler un concept existant brise le code client, même si les deux versions sont logiquement équivalentes. Quelqu'un pense que raffiner un concept, pour cette raison, devrait demander un acte explicite, et propose aussi de contraindre ce qu'un usager peut exprimer pour définir des relations de spécialisation entre concepts. Des questions de la salle permettent de clarifier la distinction entre équivalentes et fonctionnellement équivalentes. Quelqu'un pense que ce problème sera réglé par l'avènement des modules, et ne pense pas que les contraintes proposées par la proposition soient le chemin à suivre. Quelqu'un pense que l'exemple où I et I+0 montre que nous devons raffiner ce qui devrait être une forme normale dans le cas de la représentation d'une expression générique; il souhaite qu'on migre vers une représentation symbolique et sémantique plutôt que sur celle basée sur une soupe de jetons.

Quelqu'un se demande si toutes les réécritures de forme longue vers forme courte sont raisonnables, et pense que la version longue peut apparaître dans une interface alors que la courte peut suffire dans une implémentation, à titre d'exemple. Quelqu'un se dit frileux face à des hiérarchies de concepts, et parle du cas où deux vendeurs livreraient leur propre vision basée-concepts des itérateurs. Quelqu'un dit que la vision traditionnelle rend dans ce cas le code fragile. Quelqu'un rappelle une vieille discussion à l'effet que 2+2 et 4 étaient égaux ou pas dans le design des templates, et pense que les solutions de l'époque peuvent nous aider aujourd'hui. Quelqu'un dit que CWG a une liste publique de dossiers posant problème, sur la base de rétroaction venant des usagers. Quelqu'un dit que 2+2 est résolvable, clairement, mais qu'il faut un algorithme dans le standard pour éviter les réécritures divergentes d'une implémentation à l'autre.

Quelqu'un dit comprendre les deux positions sur les hiérarchies de concepts. Il mentionne qu'on peut se trouver face à une situation où deux compilateurs généreront par exemple un appel au constructeur de copie sur deux classes disjointes parce que ce sont « des classes pareilles l'une à l'autre, sauf pour le nom », et trouve cela indésirable. Quelqu'un pense que cette question pourrait être dans les Issues List pour discussion future, sans empêcher l'introduction des concepts dans le standard. Il suggère aussi de commencer avec des restrictions plus draconiennes, plus rigides, quitte à relâcher le tout ultérieurement (ce qui est plus facile à faire que l'inverse). Quelqu'un clarifie ce qu'il entend par hiérarchie de concepts.

Quelqu'un affirme que l'on dit vrai sur la question du problème entre équivalence et équivalence fonctionnelle. Il s'est avéré difficile d'implémenter les concepts sur au moins deux plateformes pour cette raison. La réécriture manuelle dans une forme courte pose aussi problème pour cette raison, car cela exige que la programmeuse ou le programmeur comprenne la réécriture réalisée par son compilateur. Quelqu'un souligne plusieurs contradictions dans le discours de plusieurs intervenants; il rejoint ceux qui estiment qu'il y a un problème avec l'équivalence fonctionnelle exprimée sur une base syntaxique, ce qui est incorrect à ses yeux et ne rejoint pas le design initial. Bjarne Stroustrup et Richard Smith sont en fait d'accord sur le fond; leur différend semble découler d'une lecture différente du texte.

Brève pause versh 55. Quelques factoïdes disparates :

On reprend les travaux vers 10 h 15.

Richard Smith poursuit sa présentation. Il montre comment décrire des relations de subsomption pour éviter de faire reposer l'équivalence fonctionnelle sur une équivalence syntaxique. Quelqu'un souligne un problème possible en pratique avec l'approche proposée. Quelqu'un pense que le problème à adresser est réel, mais que la solution proposée peut causer de nouveaux problèmes, pires que la maladie que le remède cherche à adresser. Les discussions qui s'ensuivent ne montrent pas clairement la supériorité d'une approche ou de l'autre, à mon avis. Quelqu'un fait valoir que la subsomption n'est pertinente que dans le cas où l'ordonnancement partiel des concepts intervient; à son avis, ce qui est proposé ici ne devrait pas mener à une controverse; il met aussi de l'avant que cette approche décourage les cas de requires requires qui agacent les gens. Quelqu'un dit nettement préférer ce qu'il comprend de la présentation que ce qu'il avait compris sur la base du seul texte.

Quelqu'un comprend le gain obtenu en évitant de faire dépendre l'équivalence fonctionnelle sur des jetons, mais pense que la nouvelle préoccupation fera dépendre le code résultant de la factorisation des concepts en sous-concepts (au sens où deux décompositions distinctes deviendraient équivalentes ou pas). Quelqu'un en parle comme un cas de packaging de concepts, et pense qu'on a fait un pas en avant; il en profite pour circonscrire le cas, un peu niche maintenant, où le problème surviendrait.

Quelqu'un demande à Andrew Sutton les raisons du design original. Andrew Sutton invoque le cinquième amendement  . Quelqu'un rappelle que deux écritures identiques peuvent porter des sémantiques distinctes en pratique. Quelqu'un explique les conséquences. Quelqu'un souligne l'impact de l'ordonnancement des jetons dans la proposition traditionnelle; les gens dans la salle sont partagés sur l'aspect positif ou négatif de cet impact. Quelqu'un rappelle qu'il ne faut pas voir les noms de concepts comme des alias; ce n'est pas le sens que cette chose doit porter.

La question d'un programme consommant des concepts connexes de bibliothèques A et B survient. Quelqu'un ne pense pas que ce genre de code sera brisé; il pense toutefois qu'il ne faudrait pas que le changement proposé brise la capacité de surcharger les fonctions, mais n'est pas d'avis que le code client sera réellement impacté. Quelqu'un souligne que l'ambiguïté est la meilleure solution quand le code est ambigü. Quelqu'un suggère de passer par une disambiguation à travers les noms de namespace, mais cela ne corrigera pas la situation.

Quelqu'un dit préférer, pour les concepts, des exemples concrets plus que des exemples abstrait. Quelqu'un demande si les règles mises de l'avant fonctionneraient aussi avec des traits. Semble que ce soit l'intention.

Quelqu'un amène la question des points de personnalisation. On sait comment faire avec des traits, en utilisant enable_if et des déclarations a priori, mais présentement il n'existe pas de déclaration a priori des concepts. Cela introduit une dépendance physique entre les fichiers. Quelqu'un explique que c'est parce qu'il est nécessaire de connaître l'implémentation des concepts pour résoudre les relations de subsomption. Quelqu'un fait remarquer que la proposition ne permet pas d'exprimer des spécialisations plus pointues d'un concept plus général. Quelqu'un constate que les concepts deviennent plus quelque chose comme des axiomes; plusieurs (pas tous) pensent que c'est une bonne chose.

Ville Voutilainen ouvre la porte pour un vote, maintenant ou plus tard. Quelqu'un pense qu'un vote directionnel serait pertinent. Quelqu'un pense qu'il faudrait plus en faire un Issue et y réfléchir. Quelqu'un serait à l'aise qu'on lui demande plus d'exemples et l'encourage à poursuivre. Quelqu'un propose un exemple : cowboy.draw() et shape.draw(). En POO, ce n'est pas un problème, mais en programmation générique, c'est une autre histoire. Ce qu'on veut selon lui est continuer de permettre le Duck Typing statique. Quelqu'un ajoute une fonction execute() (on rit un peu) qui appellerait draw(), mais avec des contraintes distinctes (draw() et shoot() pour un cowboy). Traditionnellement, ça aurait passé; lui pense que ça devrait être ambigü. Quelqu'un pense au contraire que le meilleur match devrait être choisi, et que le code ne devrait pas être ambigü. On fait remarquer que si shoot() est requis, alors il n'y a pas d'ambiguïté. Quelqu'un trace une distinction entre satisfaire deux concepts et avoir un lien entre ces concepts. Quelqu'un souhaite avoir ces exemples par écrit (merci!). Quelqu'un rappelle que les discussions sur le hijacking de mécanismes que nous avons aujourd'hui rappellent celles de l'époque où la proposition de surcharger operator+() a étéa été tenue. Quelqu'un rappelle que lors d'une ambiguïté, les expressions ambiguës sont supprimées du Overload Set (vive SFINAE).

Quelqu'un indique que les opérateurs && et || sont, pour fins de subsomption, de complexité exponentielle (en fait, c'est une complexité quadratique d'une complexité exponentielle... Ouch!). Le vrai problème, en pratique, est les || en fait, car template<class T> concept bool C=A<T>||B<T> signifie que A<T> et B<T> subsument C<T>. On voit des cas semblables dans des trucs aussi communs que less<T>, qui sert par défaut dans les conteneurs associatifs. Il estime que les deux options sont de l'interdire, en apposant des limites pratiques d'implémentations, ou de rendre la subsomption explicite, ou de supprimer l'ordonnancement partiel sur la base de ||. Quelqu'un indique qu'une seule disjonction peut faire dégénérer la complexité de l'évaluation du concept. Quelqu'un demande quelle est la gravité pratique du problème. Quelqu'un explicite quel est le pire cas; le cas moyen, avec les règles traditionnelles, est plus raisonnable. Quelqu'un pense que plus d'exemples serait utile. On demande si un usager devrait « rouler » un algorithme sur son propre code pour comprendre les impacts de ses concepts; présentement, on rit un peu mais la réponse serait affirmative. Cela dit, c'est un problème connexe à celui des règles de surcharge, et celles existantes sont déjà mal comprises de la majorité. Quelqu'un dit que la version originale de l'implémentation avec gcc réalisait l'algorithme qui mène au pire cas, et que leur implémentation a été modifiée depuis. Quelqu'un clarifie le fait que les disjonctions sont « cachées » dans un concept nommé et deviennent un concept atomique.

Ville Voutilainen indique qu'il faudra poursuivre cet après-midi, la question n'étant pas épuisée. Herb Sutter valide l'intérêt de la salle pour poursuivre en grand groupe; c'est le cas.

On prend la pause à 11 h 30. Ce fut un matin productif. Il y a encore des chocs de culture, surtout pour ce qui touche à la question de la langue utilisée (la langue des implémenteurs de compilateurs est différente de la langue des idéateurs de nouveeaux mécanismes). Il y a du travail à faire sur ce point.

J'ai fait un peu de correction, puis constatant que le temps filait, je suis allé me chercher un sandwich. Au retour, j'ai eu la chance de « piquer une petite jasette » avec Hans Boehm à propos des travaux de SG1. J'en ai profité pour mieux comprendre les enjeux associés aux atomic<float>, et lui à mieux comprendre pourquoi une part signficiative des entreprises de haute technologie ne fait que commencer à toucher à C++ 11 alors que C++ 14 sera bientôt « remplacé » (façon de parler, bien sûr) par C++ 17.

À mon retour dans la salle de travail d'EWG, j'ai pu bavarder avec Jean-Christian van Winkel à propos de la séance de soirée de jeudi soir, où nous discuterons de vision. On a discuté de diversité, d'ouverture, de mixité d'âge, de culture, de genres, et bien sûr de vocabulaire pour mieux se comprendre même entre experts. Il m'a dit apprécier les présentations comme celle de Bjarne Stroustrup ce matin, qui mettent d'avant les grands principes à chaque étape; je suis plutôt d'accord avec lui, bien que  je ne pense pas que ce soit les principes qui accrochent tant que leur opérationnalisation. C'est peut-être la complexité de cette bête que nous domptons ici, ce langage immense, qui fait que le fossé de vocabulaire se creuse entre les gens qui réalisent le langage, développent et entretiennent les compilateurs, et les idéateurs du langage, qui amènent du neuf au moulin mais l'expriment d'une manière générale, par des principes, et ne se reconnaissent pas toujours dans les mots par lesquels leurs idées finissent par prendre forme.

On reprend vers 13 h 15. Les gens sont ici depuis longtemps, mais il y a du travail en coulisses pour faciliter la connexions des idées.

Richard Smith reprend sa présentation. Il démontre des cas d'ambiguïté avec les constrained function template definitions, qui laissent transparaître des nouvelles sources de bogues obscurs. Par exemple :

template <class T, class ... U>
   concept bool Constructible = requires (U...u) { T(u...) };
// ensuite, Constructible<X, int> peut vouloir dire plusieurs trucs distincts

On a aussi le cas de la notation concise, f(It a,It b), où il n'est plus clair si a et b doivent être du même type ou pas. Ou le cas template<int A, X<int> B> qui a un sens différent selon le rôle de X en tant que concept ou pas. Quelqu'un suggère une syntaxe pour lever ces ambiguïtés, soit f(InputIterator T x,T y) qui dit que x est un itérateur de T et y un T, ou f(InputIterator auto x,InputIterator auto y) qui dit que les deux sont des InputIterator sans les contraindre à itérer sur un type commun. Quelqu'un demande des précisions sur le problème. Quelqu'un souligne que le problème est réel, mais qu'on a plusieurs propositions pour les adresser; il suggère que les proposeurs se rencontrent en petit groupe pour avoir un consensus préalable.

Quelqu'un dit avoir eu une réaction négative au préalable avec la syntaxe concise, mais l'avoir beaucoup apprécié à l'usage. Une fois que l'on accepte qu'on n'a pas tant un type qu'une contrainte sur une valeur, l'usage devient plaisant. Quelqu'un fait remarquer que la proposition sur la table est requise pour un concept sur un type mais ne le serait pas pour un concept sur une valeur. Quelqu'un souhaite que l'on retienne qu'il y a deux problèmes distincts ici, même s'il est possible qu'une même solution pour les deux soit possible. Quelqu'un fait remarquer (à juste titre) que, comme les concepts, un type est une contrainte sur des valeurs.

Quelqu'un demande que l'on réfléchisse à ce qui suit, car la même syntaxe décrit deux réalités :

template <int A, X<int> B> // A est int, B est un type qui satisfait int
void f(int A, X<int> B); // A est int, B est une valeur d'un type satisfaisait X<int>

Quelqu'un recommande le recours à des exemples concrets. Quelqu'un revient sur la distinction entre les concepts sur les types et les concepts sur les valeurs. Il faut selon lui être capable de matérialiser un concept sur un type dans un concept sur une valeur. Quelqu'un cherche à savoir comment on pourrait exprimer dans le premier cas ce qu'on exprime dans le deuxième cas. Quelqu'un dit que ce n'est pas possible, du moins pas avec la forme concise (ça se fait avec la forme longue). Quelqu'un rappelle que la forme courte est un outil, pas une panacée. Quelqu'un revient sur la question posée sur la cohérence des deux formes; il pense que c'est l'introduction des paramètres auto en tant que concepts les plus généraux qui sont la racine du problème. Quelqu'un n'est pas en désaccord, bien que l'incohérence demeure réelle à ses yeux. Quelqu'un a l'impression qu'on discute d'un cas niche en parlant de contraintes sur un non-type template parameter. Quelqu'un mentionne que ça survient avec auto. Quelqu'un pense que le cas étrange devrait exiger un peu de syntaxe supplémentaire, et que le cas général ne devrait pas l'exiger. Quelqu'un fait remarquer que requires est précisément cette syntaxe supplémentaire. Quelqu'un souhaite une syntaxe plus cohérente, et dit qu'on peut exiger typename pour les cas qui en ont besoin. Quelqu'un suggère de ne pas y toucher et d'utiliser la forme longue quand le besoin survient. Quelqu'un abonde dans le même sens. Quelqu'un espère que pour les usagers, le nom du concept sera suffisamment clair pour éviter toute confusion chez les usagers. Quelqu'un dit que dans son expérience, après avoir écrit une bibliothèque complète utilisant des concepts et consommée par plusieurs programmes, le problème n'a jamais été signalé. Une expérience avec des étudiant(e)s, relatée par un participant, va dans le même sens.

Quelqu'un pense qu'on peut continuer d'explorer la question mais estime que ça ne devrait pas bloquer l'acceptation du mécanisme. Quelqu'un est d'accord qu'aucune des préoccupations prises individuellement ne devrait bloquer l'acceptation du mécanisme, mais que l'accumulation de préoccupations lui semble suffisante pour que le travail se poursuive.

Ville Voutilainen demande si l'assemblée est prête pour un vote directif. Daveed Vandevoorde dit qu'il apprécierait faire sa présentation au préalable.

Terse Syntax Alternative

Daveed Vandevoorde suggère de clarifier le fait que X soit un concept un écrivant <X>, et que f(<X> a,<X> b) devrait signifier que a et b sont du même type (sinon, utilisez la syntaxe longue). Il est conscient que auto est un cas particulier. Dans sa vision, [](auto x,auto y){} permettrait x et y d'avoir deux types distincts alors que [](<typename> x,<typename> y) ferait en sorte de leur donner le même type. Quelqu'un dit que ça va selon lui rassurer les gens au début et les faire sacrer après un bout de temps car ils trouveront que la syntaxe est de trop une fois leurs repères bien situés. Quelqu'un fait remarquer que la proposition rend même la syntaxe des templates plus concise. Quelqu'un dit que ce dont il a besoin quand il appelle une fonction générique est de connaître la sémantique associée aux types, plus que savoir quels types sont génériques. Quelqu'un dit voir à cette proposition l'avantage que la syntaxe concise générée apporte, mais avoir un désaccord sur les raisons. Quelqu'un dans la salle dit apprécier la cohérence de la syntaxe proposée. Quelqu'un dit que dans sa bibliothèque, auto aurait pu être utilisé pour les paramètres, mais que Callable<T> était plus clair; il craint que l'ajout de chevrons amène les gens à utiliser auto tout simplement.

Quelqu'un remarque qu'il est facile d'en arriver, avec la syntaxe concise, à une utilisation plus verbeuse qu'avec la syntaxe longue. C'est une conséquence d'écrire void f(InputIterator,InputIterator); plutôt que template<InputIterator T> void f(T,T); en pratique. Quelqu'un dit regretter le terme Terse Syntax, qui était mal choisi quand on examiner a posteriori ce qui en est fait. Quelqu'un pense que pour les gens qui entretiennent le code, c'est très important de savoir si un nom est un template ou un concept; pour eux, la syntaxe concise est un irritant. Quelques échanges un peu musclés s'ensuivent; le sujet est sensible. Quelqu'un demande si cette syntaxe fonctionne aussi avec Callable<int>, et où placer les chevrons. Quelqu'un fait mention que l'ajout d'une telle syntaxe n'impose à personne de l'utiliser; ça ne fait pas de mal à ses yeux. Quelqu'un indique que les nouveaux mécanismes syntaxiques ajoutés au langage doivent être intégrés en tenant compte des outils modernes, par exemple la coloration du code. Quelqu'un pense qu'alléger l'écriture est le chemin à suivre pour C++, et ne voit pas la proposition comme un allègement.

Quelqu'un pense que l'idéal est d'avoir des syntaxes distinctes pour des idées distinctes. Quelqu'un pense que c'est particulièrement vrai quand les différences importent. Quelqu'un dit que le débat qui manque porte sur le fond : vaut-il la peine de distinguer visuellement le code générique du code qui ne l'est pas. Quelqu'un pense que ça a été discuté : il y a une différence par exemple entre prendre l'adresse d'une fonction normale ou d'une fonction générique (mais c'est un problème qui existe avec la surcharge de fonctions, et on n'en fait pas un plat). Quelqu'un mentionne que la syntaxe de base, template<Iterator I> I f(I,I) lui semble la plus claire. Quelqu'un rappelle le choix d'enlever le préfixe struct devant les variables de type struct, s'éloignant de la tradition C, qui avait causé des remous à l'époque. Quelqu'un rappelle une forte différence sémantique entre une surcharge de fonction ou une méthode virtuelle et une fonction générique. Quelqu'un ajoute que l'attention aux détails dans l'implémentation de ces deux familles de cas est fort différente.

Quelqu'un propose un vote surprenant : intègre-t-on le TS sur les concepts dans le IS, pour ensuite régler les irritants. Le libellé ne dit pas quand faire la fusion. Plusieurs demandent si on vise C++ 17. La réponse est est non. Certains pensent que ça va accélérer les travaux sur les concepts pour C++ 20. D'autres craignent que cela n'envoie le mauvais message à des gens qui ne participent pas aux travaux du WG21, en leur laissant croire que nous ne changerons rien. Certains rappellent que l'on a encore plusieurs débats de fond et plusieurs changements à faire, recommandant une approche plus conservatrice. Quelqu'un demande que l'on puisse continuer à faire des Breaking Changes aux concepts même s'ils sont fusionnés au IS, ce qui est confirmé. Certains mentionnent notre responsabilité collective de publiciser le fait que les concepts, même dans le IS, vont changer d'ici C++ 20. Certains expriment la conviction qu'une insertion dans le IS accroîtra la quantité de rétroaction que nous obtiendrons. D'autres sont au contraire d'avis que ce geste aura au contraire l'effet d'endommager le processus des TS. Certains estiment que le TS existant a déjà été modifié et a fait des progrès, et sont donc d'avis que le processus ne sera pas entaché par un vote favorable. Quelqu'un rappelle le précédent de <filesystem> (mais quelqu'un demande qu'on évite d'intégrer de refaire comme pour <filesystem> à l'avenir, car LWG travaille comme des fous cette semaine pour finaliser les multiples NB Comments associés à ce dossier). Le fait que pouvoir entretenir les concepts dans un TS est plus simple que dans un IS est relevé, car le nombre de ramifications à chaque changement est plus petit. Quelqu'un rappelle que dans le cas des concepts, nous avons certains NB Comments à traiter qui remontent à plus de deux ans déjà et n'ont jamais été traités. Le fait que EWG et CWG travaillent ensemble aujourd'hui est mis de l'avant.

Le vote est tenu. Nous n'avons pas de consensus (ça ressemble à une courbe normale inversée, ce qui exprime bien la polarité des opinions).

Un autre vote est ensuite tenu, à savoir si l'on devrait (de manière obligatoire) distinguer visuellement le code générique du code qui ne l'est pas dans la notation concise. Certains disent ne pas aimer la forme concise du tout, mais on leur rappelle l'existence d'une telle forme dans le TS alors c'est une préoccupation distincte.

Le vote est tenu. Nous n'avons pas de consensus  Cette fois, ça ressemble à une courbe normale aplatie.

Quelqu'un suggère qu'on donne du temps pour que les proposeurs se réunissent et discutent un peu. On demande tout de même une orientation de la part du comité sur l'approche unifiant les syntaxes de variable et de fonction pour les concepts. Quelques échanges s'ensuivent, car des gens ont découvert les différences aujourd'hui et ne sont pas sûrs de vouloir voter.

Deux votes sont à tenir, soit examiner l'opportunité de supprimer la distinction entre concept variable et concept fonction, et examiner l'opportunité de se débarrasser du mot bool. Le consensus est atteint dans les deux cas.

Deux autres votes sont tenus, à propos de la restriction de redéclarations de concepts à des formes identiques, et pour faire en sorte que l'équivalence fonctionnelle ne dépende pas d'une même séquence de jetons.

Le premier vote obtient le consensus. Le second vote obtient aussi le consensus. Pour le second, en particulier, je suis heureux car ça m'agaçait depuis le tout début.

Quelqu'un suggère un autre vote, un peu tardif, par lequel nous inclurions le TS dans le IS dès que les Issues associés à la syntaxe concise seraient réglées.

On prend une pause vers 15 h 20. J'ai un échange avec John Lakos sur le sens de l'un des votes, car nous n'avons pas compris la même chose du résultat du vote; il va vérifier auprès de Richard Smith pour voir ce qu'il en est, puisque le vote était basé sur sa présentation... et même après vérification, nous n'avons toujours pas compris la même chose. Je ne pense pas qu'on soit particulièrement bêtes, ni l'un ni l'autre, alors je pense que la valeur du vote devra être reconsidérée 

On se déplace dans la pièce de CWG pour reprendre nos activités normales. On bavarde pendant la pause (où tout le monde est sur place pour travailler, parce que CWG, c'est un peu comme ça) sur la frontière entre le Canada et les États-Unis et les nouvelles pratiques dans un sens comme dans l'autre depuis novembre 2016. L'autre sujet de blagues est mon laptop qui ne cesse de faire du bruit; j'espère sincèrement parvenir à régler ce problème avant la rencontre de Toronto.

Mike Miller annonce la reprise des travaux. Il est 15 h 45. On abordera la terminologie pour les Deduction Guides en vue de C++ 17.

Drafting for class template argument deduction issues

On examine la proposition terminologique mise de l'avant par Jason Merrill.

Quelqu'un suggère d'élargir une phrase qui ne couvre que le constructeur par défaut de manière à rejoindre l'ensemble des constructeurs rédigés par le code client.

Quelqu'un appporte de nouveaux exemples, par exemple :

template <class T> struct A {
   A(T); // #1
   A(const A&); // #2
};
template <class T> A(T) -> A<T>;  // #3, less specialized than #2

A a (42); // uses #3 to deduce A<int> and #1 to initialize
A b = a;  // uses #2 to deduce A<int> and initialize

template <class T> A(A<T>) -> A<A<T>>;  // #4, as specialized as #2

A b2 = a;  // uses #4 to deduce A<A<int>> and #1 to initialize

Quelqu'un fait remarquer l'omission d'un cas dans les règles (celui où il n'existe pas de primary class template). On examine l'intérêt de l'ajouter. Quelqu'un fait remarquer que dans le cas d'une classe vide, on génère le guide implicite pour le constructeur de copie. Quelqu'un suggère que l'existence de deux guides générant un même type et menant à une résolution ambiguë, on pourrait simplement déduire le type que les deux guides génèrent plutôt que d'échouer la déduction. C'est inhabituel pour la résolution des ambiguïtés, mais ça semble fonctionner pour ce mécanisme.

Quelqu'un se demande s'il ne serait pas pertinent d'offrir un exemple des conséquences du mot clé explicit sur les guides de déduction; il craint que les gens ne confondent ces guides avec les constructeurs explicites de la classe déduite, alors que l'un n'implique pas l'autre. Quelqu'un rappelle l'impact des guides explicites, particulièrement dans le cas du list initialization.

Quelqu'un dit que LWG se questionne sur un cas un peu compliqué, soit la déduction d'un vector<size_t> qui requiert l'ajout de guides explicites supplémentaires. On discute de l'ajout d'un exemple pour montrer que ça fonctionne et comment y arriver.

Quelqu'un souligne au passage que Core Issue 2 (qui n'est pas encore fermée) est assigné à John Spicer. On se bidonne un peu.

Quelqu'un dit qu'il existe d'autres situations que les simple declarations qui sont connexes et devraient être couvertes dans la terminologie.

Quelqu'un pense que tôt ou tard, nous aurons besoin d'un = delete pour ce mécanisme, ou de quelque chose de connexe pour supprimer certaines surcharges. Quelqu'un dit être conscient du besoin, mais n'est pas sûr de la meilleure expression pour ce mécanisme. Quelqu'un propose une approche technique existant dans le langage déjà. Quelqu'un pense que = delete dans sa forme actuelle (en fait, ça n'existe pas pour C++ 17, mais on lui a dit que ce pourrait être un DR, ce pour quoi la salle est plus froide – c'est de la nouvelle syntaxe, après tout) serait déjà utile pour supprimer, par exemple, la déduction d'un valarray<T> à partir d'un T*. Quelqu'un pense que dans le cas où le code client contient des constructeurs qui ne « mappent » pas élégamment au substrat modélisé, on risque de générer du code insensé. Quelqu'un fait remarquer que son banc d'essai était la bibliothèque standard, qui est dans l'ensemble plutôt bien conçue sur ce plan, mais ajoute que le mécanisme n'est pas obligatoire pour qui n'en veut pas.

GB66 – Replacing sized delete

Le problème souligné tient au cas où il n'est pas clair s'il faut privilégier la version de operator delete recevant une taille en paramètre et celle n'en recevant pas, dans le cas où l'un des deux a été surchargé mais pas l'autre. L'exemple proposé pour illustrer le propos semble simple, mais amène des questions :

void operator delete(void*) noexcept; // #1
// void operator delete(void*, std::size_t) noexcept; #2
void f() {
  int * p = new int(42);
  delete p;    // calls user-declared #1 or built-in #2
}

Quelqu'un nous amène à §18.6.2.1 p. 16, qui indique que par défaut, le code qui accepte une taille relaiera simplement l'appel à la version qui n'en accepte pas, pour faciliter la transition. On relaie l'information à l'originateur du commentaire pour voir si nous avons bien compris sa remarque.

On discute d'un cas problématique de placement new mal foutu décrit à §5.3.4 p. 23. Quelqu'un ne pense pas que ce soit le cas qui ait donné naissance à GB66.

On reviendra sur cette question quand nous en saurons plus.


Quelqu'un revient sur le cas un peu particulier des guides de déduction pour unique_ptr, §20.11.1.2. Quelqu'un pense que la terminologie existante ne permet pas de déduire le type à générer pour le moment. Faudra rendre la terminologie plus spécifique que using pointer = see below, qui n'est pas du C++ et ne dit pas comment réaliser la déduction, ou si même elle est possible.

Jason Merrill nous présente une nouvelle version de la terminologie.

Quelqu'un fait remarquer que la terminologie proposée, « If a placeholder for a deduced class type appears as a decl-specifier in the decl-specifier-seq of a variable declaration (including e.g. a condition (6.4), for-range-declaration (6.5.4), or static data member (9.2.3.2)) , the placeholder is replaced by the return type of the function selected by overload resolution for class template deduction (13.3.1.8). » ouvrirait la porte à la déduction des paramètres génériques des fonctions, un mécanisme involontaire et pas nécessairement désirable (le terme « variable declaration » est trop fort).

On retravaille la formule pour réduire la portée de ce qui peut être fait. Le même passage est reformulé comme « If a placeholder for a deduced class type appears as a decl-specifier in the decl-specifier-seq of a variable definition (including e.g. a condition (6.4) or for-range-declaration (6.5.4)), or of a static data member declaration with a brace-or-equal-initializer that appears within the member-specification of a class definition (9.2.3.2)) , the placeholder is replaced by the return type of the function selected by overload resolution for class template deduction (13.3.1.8). », ce qui est plus contraignant.

Reste la question de deux guides générant le même type sur la base de déductions ambiguës. Quelqu'un suggère qu'il faille d'abord produire un exemple concret avant de formuler une terminologie. On semble d'accord avec cette position. Quelqu'un esquisse une direction susceptible de nous mener à une telle situation. On penche pour traiter ça dans un DR, le cas échéant.

Quelqu'un parle d'un autre cas de DR possible, du fait que nous générons en fait des constructeurs génériques avec ce nouveau mécanisme, ce qui peut générer des surprises.

Quelqu'un identifie un autre cas possible de problème avec la formulation existante. On va prendre le temps d'exprimer une liste exhaustive des cas possibles, ce qui devrait régler le problème. On y reviendra.

Je me suis pris une bière (un peu moins chère, car c'était le Happy Hour de l'hôtel, mais chère tout de même), puis je suis allé à ma chambre parler un peu à Za et à Marguerite qui était à la maison (semble qu'elle viendra me cueillir à l'aéroport lors de mon retour dimanche, avec mon pus jeune Ludo, ce qui est bien chouette de sa part). Sur le chemin, j'ai croisé Paul Preney, un nouveau membre de la délégation canadienne, qui semble bien sympathique. Je vais essayer d'aller manger une bouchée avec lui cette semaine, question de faire un peu sa connaissance.

J'ai travaillé un peu, je suis allé me chercher un plat de nouilles non-loin, j'ai travaillé encore un peu par la suite, mais je me suis endormi tôt, encore une fois vers 20 h. Le décalage horaire, le stress et les journées de travail très lourdes ont eu raison de moi cette fois.

Jour 2 1er mars 2017

Debout versh, pour compenser mon sommeil hâtif de la veille et préparer la journée. Lectures, douche, j'écoute un peu la radio de Radio-Canada grâce à Internet (et je reste chaque fois stupéfait que les émissions de télévision, elles, soient bloquées, même si je n'en regarde que vraiment très peu). J'entends entre autres Judith Lussier, qui dit avoir abandonné son rôle de chroniqueuse car c'était devenu trop difficile (harcèlement, pression, menaces et autres idioties), puis Nabila Ben Youssef qui a quitté le Québec parce qu'elle s'y sentait moins libre qu'auparavant (on parle d'une humoriste qui a pris des positions pour la laïcité pendant les remous des dernières années) et je me sens bien triste tout à coup. Le vivre ensemble a beaucoup souffert chez nous ces dernières années.

Plusieurs lectures (je vais finir par reprendre le dessus), dont celle d'une proposition que je dois défendre en après-midi et que je n'avais pas bien intégré encore. Je me suis aussi joint à un groupe de discussions sur Slack, un outil de clavardage particulier dans lequel on trouve un groupe spécifiquement destiné au langage C++, pour faciliter la communication avec les experts ici et celles / ceux qui ne peuvent pas se présenter aux rencontres du comité.

En marchant vers la salle de travail de CWG, j'ai croisé la toujours charmante Lisa Lippincott, avec qui j'ai bavardé de la météo (sujet inépuisable, mais honnêtement, c'est moins lourd cette semaine que je ne l'aurais cru : il y a un petit vent, c'est un peu gris aussi, alors rien d'écrasant), le sympathique Marshall Clow que j'ai remercié car LWG fait un travail colossal sur <filesystem> cette semaine, et le chic type dont le nom m'échappe qui m'a reconnu en début de semaine et qui m'a avoué lire ce que j'écris (c'est toujours étrange d'entendre ça), que ses collègues font de même, et avec qui j'ai bavardé des aléas de l'implémentation des exceptions.

Assis chez CWG, la bonne nouvelle du jour était que Kate Gregory (une très chic dame) semble avoir survécu à ce vilain cancer qui l'avait affligé. Gor Nishanov est passé nous saluer mais nous ne le verrons qu'un peu plus tard aujourd'hui. Ensuite, Bjarne Stroustrup et Gabriel Dos Reis sont venus se joindre à nous car nous discuterons des modules avec eux ce matin.

Ls travaux débutent versh 5. La salle est pleine.

D0583R0 – Modules: Contexts of Template Instantiations and Name Lookup

Le texte préparé par Gabriel Dos Reis couvre l'exemple discuté lundi. Des divers exemples présentés, Gabriel Dos Reis suggère qu'on en examine deux de plus près. Le premier est :

// X.h
namespace Q {
   struct X { };
}
// Module M1:
#include "X.h"
// global module
namespace Q {
   X operator+(X,X);
   // private implementation details
}
module M1;
export template<typename T>
   void g(T t) { t + Q::X{ }; }
void j(Q::X x) {
   g(x); // #1
}
// Module M2:
#include "X.h"
module M2;
import M1;
void h(Q::X x) {
   g(x);
   // #2
}

Cet exemple, selon lui, fonctionne tel qu'attendu. Le deuxième est plus délicat :

// Module A:
module A;
export template<typename T>
   void f(T t) { t + t; }
// Module B:
module B;
import A;
export template<typename T>
   void g(T t) { f(t); }
// Module C: (c'est l'interface dans ce cas) 
struct S { };
S operator+(S,S);
module C;
import B;
export template<typename T>
   void h(T t) {
      g( (t, S{ }) ); // argument is comma expression
   }
// Main translation unit:
import C;
void i() {
   h(0);
}

Quelqu'un décrit pas à pas le contexte d'instanciation des éléments clés, l'impact d'ADL, et les attentes envers les compilateurs. Quelqu'un s'interroge sur l'importance (ou pas) de placer operator+ dans le module global. Quelqu'un explique les règles dans ce cas. Quelqu'un pense qu'avec les règles proposées, une fonction générique appelant une fonction qui ne l'est pas interagirait de manière surprenante avec les règles traditionnelles de lookup. Quelqu'un pense qu'il faudra ajouter un petit quelque chose pour l'association entre types et namespace partitions; cette association est sous-entendue, mais la pratique dans le texte du standard est d'éviter les sous-entendus pour réduire les divergences de comportement des implémentations. La section §3.4.2 [basic.lookup.argdep] demandera un peu de travail en ce sens. On s'entend sur ce qui doit être fait.

Quelqu'un souligne que le texte ne rend pas clair le fait que l'on n'exporte pas automatiquement tout ce qui est dans le module global. Dans l'exemple, A forme decltype(declval<S>()+declval<S>()) mais rien ne rend évidente l'exporation de operator+(S,S) dans C. Déterminer en général ce qui doit être exposé, particulièrement avec un template, est un problème vraiment difficile à résoudre. Quelqu'un dit qu'il faudrait vraiment exporter operator+(S,S), mais on souligne que les règles existantes ne rendent pas simples l'exportation des symboles dans le module global. Quelqu'un note que ce qui apparaît dans le module d'interface doit être exposé dans une certaine mesure. Quelqu'un fait remarquer que ça peut devenir dispendieux si le module d'interface inclut des en-têtes lourds comme <windows.h>.

Sur le plan conceptuel, S n'appartient pas au module C ici; elle apparaît dans l'interface mais loge dans le module global. Il semble y avoir un besoin de clarification terminologique ici. Quelqu'un demande si l'exemple le plus récent est supposé fonctionner ou pas. Il y a un désaccord dans la salle. Quelqu'un dit que clang supporte cet exemple, même si la syntaxe est un peu différente de celle du TS actuel. Une des nuances entre les deux tient à ce qui est exporté ou pas de manière transitive par un module. Quelqu'un explique pourquoi les fichiers temporaires, dans les termes existants, seront immenses.

Le support possible des en-têtes précompilés (les fichiers .pch) entre dans les débats, mais certains ne sont pas convaincus de l'intérêt de tenir compte des .pch avec l'avènement des modules de toute manière. C'est une question pratique : des produits existants dépendent des .pch et ne pas les supporter entravera l'adoption du mécanisme. Certains sont d'avis que c'est un signe que le design, dans la décision de ne pas exporter ce qui apparaît dans le module global, est défectueux; selon eux, la solution est simplement de remplacer les .pch par des modules, justement. Quelqu'un rappelle l'audience à l'ordre, du fait que les .pch ne font pas partie du standard. Quelqu'un demande une clarification, que quelqu'un donne et que je ne répéterai pas ici, mais le problème devient limpide.

Un nouvel exemple est développé, sur la base du précédent :

#include <string>
import B;
module C;
export template <typename T>
  void f(T t) {
     g( (t, string{}) ); // operator comma
  }

À partir de ce point, je suis encore en processus de remplacement des noms individuels par des noms génériques; je mettrai la page à jour quand j'aurai terminé

Glossaire

Plusieurs termes tirés du jargon du comité apparaissent dans ce document. J'ai essayé de les regrouper ici. Tout ce qui suit est informel, alors prenez-le avec un grain de sel.

Acronyme Signification En détail (informellement)

ABI

Application Binary Interface

La forme que prend l'interface compilée entre les modules (au sens large du terme) d'un système. En C++, il n'y a pas d'ABI commune entre le fruit des implémentations de divers vendeurs, alors cette question est sensible

NB

National Body

Pays participant au processus de standardisation

CD

Committee Draft

Le premier jet du standard, qui sera soumis aux pays pour leur donner une opportunité de se prononcer sur le contenu et de soumettre des demandes de correctifs

CWG

Core Working Group

Le groupe de gens qui cherchent faire raffiner ce qui est au coeur du langage, incluant la grammaire, les éléments qui impliquent l'ajout de mots clés (mots de vocabulaire ayant un rôle prédéfini) contextuels ou non, ce genre de truc. Intersecte en partie avec EWG

DIS

Draft International Standard

Étape intermédiaire entre le CD, suivant les NB Comments, et le IS.

DR

Defect Report

Document rapportant une défectuosité dans le texte du standard, et mettant typiquement de l'avant une possible solution à l'attention du comité

DTS

Draft Technical Specification

Document de type « premier jet », qui se veut complet et est soumis à la discussion mais n'a pas encore à être implémenté (sauf à titre volontaire et expérimental)

EWG

Evolution Working Group

Le groupe de gens qui cherchent faire avancer le langage à proprement dit, incluant la grammaire, les éléments qui impliquent l'ajout de mots clés (mots de vocabulaire ayant un rôle prédéfini) contextuels ou non, ce genre de truc. Intersecte en partie avec CWG

IS

International Standard

La norme à laquelle les implémenteurs doivent se conformer.

LEWG

Library Evolution Working Group

Le groupe de gens qui cherchent à voir dans quelle direction faire évoluer la bibliothèque standard : quoi y ajouter, quoi en retirer (ça arrive!), comment s'y prendre pour que le tout se passe bien, etc.

LWG

Library Working Group

Le groupe de gens qui cherchent à comprendre les problèmes existants dans la spécification existante de la bibliothèque standard, et qui visent à déterminer les correctifs optimaux dans chaque cas. Retenez que la bibliothèque telle que définie par le standard est une spécification, qui dit aux gens ce qui doit être fait, mais pas nécessairement comment le faire. Cela dit, les participants du LWG sont typiquement des gens qui implémentent la bibliothèque standard au quotidien

NAD

Not a Defect

Une préoccupation mise de l'avant par un document qui nous a été soumis est considérée, mais nous statuons qu'il ne s'agit pas d'un défaut

NaN

Not a Number

http://en.wikipedia.org/wiki/NaN

NB Comments

National Body Comments

Une fois un CD livré, celui-ci est examiné par les pays participant au processus de standardisation. Ceux-ci livrent, en tant que pays, des commentaires pour améliorer le CD avant qu'il de devienne un DIS, puis un IS.

PDTS

Pre DTS

Un pré-DTS 

QoI

Quality of Implementation

Aspect laissé à la discrétion des vendeurs, qui dépend de la qualité de leur implémentation (p. ex. : la nature des messages diagnostics produits)

SG

Study Group

Un paquet d'experts sur un sujet qui travaillent ensemble à faire avancer un dossier, en tout ou en partie, mais à titre exploratoire. Je fais entre autres partie de SG14, le groupe d'études pour ce qui a trait aux systèmes à basse latence. Les groupes d'étude existants sont :

  • SG1 : Concurrency and Parallelism
  • SG2 : Modules
  • SG3 : File System
  • SG4 : Networking
  • SG5 : Transactional Memory
  • SG6 : Numerics
  • SG7 : Reflection
  • SG8 : Concepts
  • SG9 : Ranges
  • SG10 : Feature Test
  • SG12 : Undefined and Unspecified Behavior
  • SG13 : I/O
  • SG14 : Low Latency

TS

Technical Specification

Un document qui ne fait pas officiellement partie du standard mais qui permet à tous d'expérimenter et de valider que les idées mises sur la table fonctionnent en pratique

WD

Working Draft

Littéralement : un document (formel) de travail

WG

Working Group

Un paquet d'experts sur un sujet qui travaillent ensemble à faire avancer un dossier, en tout ou en partie. Notre groupe est WG21; les langage gens qui travaillent sur le langage C forment le groupe WG14,, et il y en a plusieurs autres, dont WG23 auquel je participe et qui porte sur les vulnérabilités dans les langages de programmation


Valid XHTML 1.0 Transitional

CSS Valide !