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 ethics, 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). Should you think it would be appropriate for me to remove things from this page, please tell me and I will proceed switfly.
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 à Lucia Lepage), 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. Merci spécial à Gabriel Aubut-Lussier pour plusieurs corrections : ton regard aiguisé est apprécié!
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 sept délégués canadiens (Michael Wong, Botond Ballo, Hubert Tong, JF Bastien, Tony Van Eerd, Duncan Exon Smith et moi-même)
Pour un peu de bagage supplémentaire sur l'événement, voir :
Pour les journaux de voyage d'autres participants, voir :
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
J'ai groupé les jours -2 et -1 car, avec le décalage horaire et le transport, ce fut au fond une seule longue journée pour nous
Pour ce voyage, j'innove en amenant mon épouse Za avec moi. Celle-ci pourra voyager un peu pendant nos travaux, et il se trouve que le jour du vote coïncide avec notre anniversaire de mariage, ce qui nous permettra d'être ensemble plutôt que de vivre un décalage horaire de sept heures l'un par rapport à l'autre ce jour-là.
Puisque je travaille tout le temps pendant les rencontres du comité, Za est accompagnée de sa chic amie Cindy. Elles pourront apprendre le finnois et explorer les lieux alors que moi et les autres membres du comité débattront dans des salles fermées avec beaucoup d'intensité et de caféine.
La journée commença de manière spectaculaire. Il faut comprendre que nous avons plusieurs animaux de compagnie à la maison, en particulier des chats (qui seront visités à tour de rôle par des amies de Za pendant notre absence, et qui auront à l'occasion la compagnie de nos grandes filles qui viendront profiter de la piscine en notre absence) et des chiens, qui ont besoin de plus d'attention et auxquels nous avons trouvé une pension.
Il se trouve que ce matin, à environ deux heures du moment de quitter pour l'aéroport, un problème a fait que nous avons dû trouver une nouvelle pension pour les chiens, puis les relocaliser physiquement (les changer de pension... et de ville!) alors que nous étions dans les derniers prépartifs et qu'il fallait encore déplacer les enfants les plus jeunes chez les adorables grands-parents qui prendront soin d'eux en notre absence (Danielle et Jocelyn pour une bonne partie, de même que Lucille, Réal et Jacqueline pour quelques jours chacun... On vous aime et on vous remercie du fond du coeur!). Ce fut sportif et ça a compliqué quelque peu l'amorce du voyage. On gros merci à Réal, qui a gracieusement offert de nous mener à l'aéroport, pour sa patience.
Le voyage s'est fait en trois temps :
En tout et partout, donc, on parle de tout près de 17 heures de transport, auquel il faut ajouter le temps d'attente initial à Montréal et le transport de l'aéroport de Oulu à l'hôtel où se tient la rencontre. Une fois installés, nous avons mangé une bouchée avant de tomber d'épuisement, donc nous avons passé un peu plus de 24 heures éveillés (à part les périodes de sommeil léger en vol).
Quelques remarques éparses :
Il est minuit. Il me reste à passer quelques documents en revue et je re-dormirai quelques heures avant de me mettre au boulot
J'ai travaillé une bonne partie de la nuit mais il me reste quelques trucs à lire pour dire que j'ai au moins survolé tous les sujets qui seront couverts cette semaine. J'ai aussi constaté que j'ai quelques obligations personnelles :
Dans la chambre, nous avons déjà réussi à à faire une bêtise (un disjoncteur a cuit quand une de mes compagnes de voyage a essayé d'utiliser un fer plat dans la salle de bains). C'est amusant, dans la mesure où on n'a pas mis le feu à l'hôtel. J'ai averti la réception.
Comme c'est souvent le cas, il n'y avait pas de badge à mon nom (semble que je devais signaler ma présence dans un questionnaire en ligne qui m'a échappé cette fois) mais on ne s'en formalise plus ici (c'est comme un Running Gag). Herb Sutter est de bonne humeur et m'a fait un High Five en voyant ça. Il s'est couché tard hier en regardant la finale de la NBA (c'était un septième match enlevant apparemment).
Jonathan Caves m'explique comment se rendre à un endroit où la bière est bonne, à quelques coins de rues de l'hôtel. J'essaie de mémoriser le tout pour référence future.
Ville Voutilainen nous accueille. Il y a des caméras dans la salle pour fins de promotion de son entreprise (qui paie pour l'événement). John Spicer nous indique de nouvelles règles pour la prise des présences (on signe une seule fois, pas à chaque jour; c'est moins lourd). Ville Voutilainen nous indique qu'un repas nous sera offert ce midi et qu'un événement de type Town Hall Meeting se tiendra ce soir à quelques coins de rue d'ici.
Clark Nelson explique les règles de votation. On fait un tour des gens présents; bonne nouvelle, nous avons neuf pays officiellement représentés, incluant la Russie et la Bulgarie (cool!) et un retour de la France et de l'Allemagne qui n'avaient pas été formellement représentés ces dernières années.
On examine les TS et les rapports de leur éditeurs. Herb Sutter indique qu'on n'a pas encore les résultats formels du vote pour faire des modules un TS mais ça ne saurait tarder. Nicolai Josuttis dit qu'étant donné l'importance de la rencontre, où l'on votera C++ 17, il aimerait qu'on ait un esprit clair quant aux changements possibles cette semaine qui pourraient impacter la bibliothèque standard. Alisdair Meredith mentionne la génération par défaut des opérations de comparaison (qui dépend de la constitution interne des classes et pourrait surprendre). Herb Sutter demande qu'on ne tienne pas ces débats en plénière. Ville Voutilainen parle de l'importance de ces discussions qui se tiendront plus tard aujourd'hui. Jeffrey Yasskin dit que les opérateurs de comparaison sont sur sa courte liste. Alisdair Meredith rappelle quelques cas (le mouvement généré ou non par défaut, entre autres, et constexpr) où le texte émis par CWG a affecté radicalement le design de la blbiothèque standard.
Nicolai Josuttis dit trouver difficile de suivre l'évolution de C++, et demande si un résumé des votes pourra être publié avant la fin de la semaine. Ville Voutilainen recommande de lire les notes produites dans les groupes de travail pendant les travaux. Quelqu'un suggère qu'on demande aux auteurs de présenter les subtilités en plénière, au besoin.
Les WD sur la table semblent convenir aux gens présents : le langage lui-même, la bibliothèque standard, les modules, la réseautique. Herb Sutter suggère que les travaux sur les TS se fasse de manière asynchrone, par sous-groupes de spécialistes, pour améliorer la fluidité des travaux.
Semble qu'il y ait des erreurs dans la liste des participants à la rencontre de Jacksonville (PL22.16, pas WG21), mais c'est compliqué alors on corrigera le tout hors de la plénière.
Pour les groupes de travail :
Pour les soirées, on débutera à 20 h (sauf lundi soir) :
Ville Voutilainen iindique que c'est très facile d'organiser une rencontre de WG21 car Jens Maurer organise tout. On applaudit Jens Maurer.
Sur le chemin, nous avous droit à un petit goûter : des noix, des fruits séchés, des fruits frais (melon d'eau, oranges, pommes), des bouchées salées (crêpes avec mousse au saumon fumé, petites quiches au renne fumé, pas vilain du tout, ça ressemble à un jambon parfumé je dirais), des jus, des eaux parfumées aux fruits frais et, évidemment, du café (incluant une machine à espresso, mais je fais mon rustre et je prends du café filtre car ça va me durer plus longtemps). Je saisis mon badge fraîchement créé (mon nom est écrit à la main, comme c'est souvent le cas). Je ne suis pas le seul dans cette situation, évidemment. J'ai rencontré Neil MacIntosh, aussi gentil en personne que par écrit.
Je discute brièvement avec Marshall Clow pour être certain de ne pas manquer les discussions autour de la proposition de Brent Friedman, qui m'a demandé de l'accompagner. Ça se fera probablement cet après-midi, LWG ayant à prioriser les « issues » ce matin et à s'assurer de bien couvrir les Show-Stoppers.
CWG se rencontre dans « le donjon », une pièce sans fenêtres au sous-sol (mais plus grande que ce à quoi j'ai été habitué dans les rencontres précédentes) où nous nous adonnons à l'habituelle valse des prises de courant et des adaptateurs de toute sorte (je n'avais pas réalisé que les britanniques ont des adaptateurs différents des autres peuples européens). J'aime bien l'ambiance quasi religieuse de CWG, qui est un groupe très différent des autres, même si sur le plan des affinités techniques je suis près de LWG et de LEWG si on regarde le tout franchement. Je vais donc faire de CWG mon nid, comme à l'habitude, mais me promener un peu selon les besoins, comme je l'ai fait à Kona.
On sera autour de 15-16 personnes cette semaine à CWG, selon toute probabilité, mais avec des invité(e)s selon les thèmes évidemment.
Mike Miller nous indique que notre mandat sera de traiter la terminologie des propositions visant C++ 17 rapidement. Quelques gens (dont moi) devront quitter occasionnellement.
Jens Maurer dit que ses propres propositions sont destinées à CWG mais doivent être discutées dans EWG d'abord, au cas où il y aurait des changements.
Sur le plan logistique, nous viserons un lunch de 12 h à 13 h pour sauver du temps (techniquement, la pause est de 12 h à 13 h 30 mais on a trop à faire pour ne pas revenir plus tôt).
Jens Maurer explique l'intention derrière ce mécanisme, pour réduire les instanciations de templates dans des circonstances où nous procédons actuellement par des spécialisations partielles et enable_if. Il semble qu'un problème potentiel tienne à l'ajout possible du mot constexpr devant une déclaration de variable logée dans un if, mais l'assentiment général dans la salle semble être « allons-y ainsi et on ajustera s'il y a des mécontents » pour ne pas bloquer le processus de ce mécanisme quand même assez intéressant.
Richard Smith mentionne que les templated entities sont utilisées dans le texte de la proposition mais qu'il y a un risque que cette proposition ne passe pas pour C++ 17. Il y avait une entente lors d'une téléconférence il y a quelques mois pour extraire cette partie du texte (Core Issue 2174), donc ce n'est qu'un oubli.
Dinka Ranns demande ce qui se produit si une condition interne d'un constexpr if n'est pas réalisée mais celles d'une condition externe l'est. Il se trouve que ce n'est pas une différence observable.
Maxim Kartashev s'interroge sur discarded statement, qui semble avoir des impacts sémantiques alors qu'il s'agit en fait d'une structure grammaticale. Jens Maurer dit que c'est un peu l'intention, mais que la sémantique est simple. John Spicer indique qu'il pourrait être pertinent de distinguer les règles pour constexpr if dans un template et hors d'un template. Ceci entraîne quelques débats. On garde cette remarque brillante de John Spicer sur le Wiki pour un éventuel « I told you so ».
Richard Smith demande s'il serait sage d'ajouter un terme grammatical distinct pour le sous-énoncé découlant d'un constexpr if. Jens Maurer n'est pas sûr, estimant que la formulation « longue » utilisée pour le moment est suffisamment courte pour être utilisée en pratique. Mike Miller suggère que l'on examine cette avenue si d'autres cas surviennent éventuellement (c'est possible)
Faisal Vali demande une précision sur le terme utilisé pour décrire l'entité englobant un constexpr if. On en arrive rapidement à une écriture plus fluide. Maxim Kartashev fait remarquer que l'écriture d'actions qui ne sont pas prises par le compilateur est difficile. Richard Smith exprime un inconfort face à l'idée de « immediately enclosing ». Jens Maurer dit qu'il préférerait ne pas écrire les ajustements maintenant et se demande s'il est nécessaire de régler le dossier dans l'immédiat, mais Richard Smith rétorque que c'est important de régler ce texte tout de suite, le tout ayant un impact sur la sémantique. Richard Smith et John Spicer discutent des impacts de cette terminologie sur les captures des λ génériques. Hubert Tong et Richard Smith discutent de l'écriture existante des règles de capture des λ génériques. La question des de savoir si c'est un problème avec l'écriture des règles de capture des λ génériques ou avec cette proposition-ci.
Richard Smith met de l'avant le fait qu'une λ générique dans laquelle on déplace un constexpr if qui compilait avant déplacement devrait compiler après déplacement. John Spicer est d'accord mais ce n'est pas le coeur de sa préoccupation. On semble converger vers la vision de John Spicer : faudrait retarder la génération des règles de capture, et ça semble fondamental aux yeux de Richard Smith. On va devoir revenir à EWG avec une explication claire des raisons de nos préoccupations, à savoir que deux options ont été découvertes et que nous souhaitons leur avis.
Comme c'est souvent le cas, Richard Smith nous pond un exemple (merci à Dinka Ranns de me l'avoir fait suivre; je reçois les messages de CWG normalement, mais pour une raison que j'ignore celui-ci ne se rendait pas) :
template<typename Iter>
void f(Iter a, Iter b) {
const int v = 10;
auto do_something = [&] (auto thing) {
if constexpr (is_random_access_iterator<Iter> && is_integral<decltype(thing)>)
*(a + 1) = v;
};
do_something(5);
do_something("foo");
}
On ne veut pas que ce code ne pose un problème dans une branche non discartée, mais cela impliquerait changer les règles de capture dans une λ générique.
Danil Tarakarov mentionne qu'il se peut qu'une branche discartée soit le seul point d'instantiation d'un template, et pense qu'il faudrait clarifier ce point dans la formulation choisie. Selon lui, le fait que cette réalité puisse mener à la génération de types inutilisés en pratique est digne de mention. John Spicer pense que ceci n'est pas nouveau, et s'avère dans les templates en général. On fait un peu de tableau ici pour jongler avec des exemples. Il y a une différence de perspective sur les obligations de génération de code du compilateur.
Hubert Tong mentionne que nous avons été chanceux jusqu'ici de ne pas frapper un cas d'accolades non-balancées... à l'hilarité générale.
On travaille encore un peu sur la formulation menant à discarter ou non une branche. Faisal Vali se questionne sur l'utilisation des termes instantiation et substitution et leur usage formel. John Spicer indique qu'on devrait définir plus formellement l'idée derrière instantiation éventuellement; Hubert Tong et Richard Smith se bidonnent à propos des cas limites qui vont sortir de ces éventuelles discussions.
Mike Miller va faire le suivi avec EWG pour la préoccupation en lien avec les règles de capture dans une λ générique. On arrête vers midi; cet après-midi, on commencera par D0135 sur les garanties de Copy Elision.
Dîner agréable, fourni par l'hôtel (je ne sais pas si c'est seulement aujourd'hui ou toute la semaine). Format buffet, mais avec de la nourriture de qualité, incluant de la viande séchée, des noix, des fruits (frais et secs), du fromage pas mal, diverses salades, plusieurs sortes de viande, des légumes racines... Goûteux et coloré.
J'ai eu la chance de bavarder avec Marshall Clow, Mike Miller et Michael Herrick (de EDG) pendant le dîner. Ça m'a permis d'en apprendre plus, en particulier sur Marshall Clow, et d'être averti qu'il y a beaucoup de moustiques en soirée aux abords de la rivière qui borde l'hôtel (vaut mieux prendre des marches dans ce secteur le jour plutôt que le soir). En retour, il semble qu'on puisse bien manger juste l'autre côté de la rivière, alors à investiguer pour la fin de la semaine.
Marshall Clow me dit que la proposition de Brent Friedman devrait être traitée après la pause de l'après-midi, alors je pourrai travailler avec CWG en attendant.
Une pensée pour mon amoureuse Za et sa chumette
Cindy qui
découvrent les lieux. Je suis curieux d'avoir de leurs nouvelles tantôt! Pendant
les travaux de l'après-midi, Za m'a envoyé une photo de leur repas (mioum!).
Semble qu'elles font du vélo
On reprend vers 13 h.
Richard Smith met en situation : l'objectif est de garantir l'élision de copies dans certains cas, pour que la création de temporaires sujettes à être élidées soit escamotée de manière prévisible (présentement, c'est une question de QoI même si, en pratique, tous les compilateurs le font).
J'échange brièvement avec Richard Smith sur le sens de discarded prvalue, où le mot « discarded » a un effet distinct de celui discuté plus tôt aujourd'hui (selon Richard Smith, le sens attendu ici touche aux cas où on ferait un (void)expr par exemple, mais où expr doit tout de même être généré et peut créer un objet).
Un effet de ce changement est qu'une expression comme la suivante :
T x = T(T(T()));
... n'appellera qu'un seul constructeur de T, et que ce sera garanti par la spécification du langage.
Exprimer ce genre de truc (le sens donné au concept de valeur, selon le contexte; la durée de vie des objets résultant de l'évaluation d'une expression selon l'usage qui en est fait) est complexe, alors on échange sur la terminologie à utiliser pour être aussi clair que possible dans les circonstances.
La terminologie choisie vise aussi à rendre des horreurs comme ceci non-spécifiées :
extern struct D d; struct D { D(int a) : a(a), b(d.a) {} int a, b; }; D d = D(1);
Hubert Tong soulève des questions sur le moment précis de l'initialisation de l'objet retourné par une fonction, en particulier lorsqu'il doit y avoir une conversion implicite dans la procédure. Richard Smith reconnaît un problème ici, mais ce problème précède chronologiquement la proposition, alors il faudrait selon lui soumettre une demande de correctif à part entière plutôt que modifier le texte proposé.
Jens Maurer et Mike Miller soulèvent des interrogations sur la terminologie utilisée pour clarifier le moment où survient un appel au destructeur pour une temporaire. On retravaille la formulation pour clarifier le tout.
Richard Smith doit nous quitter pour aller présenter une proposition devant EWG. On profite de la présence de Clark Nelson pour discuter de D0035
Clark Nelson présente les raisons de sa présentation de ce document devant CWG, soit l'ajout d'une macro prédéterminée nommée __STDCPP_DEFAULT_NEW_ALIGNMENT__ pour identifier les vendeurs qui ne supportent pas l'ajout du paramètre supplémentaire de type std::align_val_t à l'appel de new.
Mike Miller fait remarquer que le texte proposé ne semble pas tenir compte des tableaux. Clark Nelson indique qu'en pratique, c'est operator new qui est appelé, et qu'il trouve ardu d'exprimer quelque chose qui tiendrait correctement compte de la réalité. Mike Miller indique que la terminologie proposée ne décrit tout de même pas l'intention clairement dans le cas d'un appel à operator new[]. Il ajoute que le recours à une signature dans la terminologie semble exclure des cas a priori pertinents (les cas no-throw, en particulier). On envisage utiliser allocation function, qui exclut les trucs comme malloc() qui tombent dans une autre catégorie terminologique.
Clark Nelson mentionne que l'ajout qui nous semble un peu trop restrictif est une demande de LEWG. Il demande si transformer le passage en note non-normative peut suffire à satisfaire les souhaits de LEWG tout en passant le teste de la rigueur normative. Mike Miller dit oui, et suggère d'ajouter un « etc. » à la note non-normative pour clarifier l'intention.
John Spicer mentionne qu'il serait important que si un compilateur supporte operator new(size_t, align_t), il ait l'obligation de supporter aussi operator new[](size_t, align_t). Clark Nelson est résistant, ayant peur que l'on ne dérape dans la rigueur, mais Jens Maurer suggère une formule simple et qui semble acceptable.
On soulève la question du support des formes acceptant un std::nothrow_t. Le nombre de formes à expliciter croît rapidement. Mike Miller vérifie le texte existant et semble que ce soit déjà couvert par §18.6.2.1 dans une formule d'ordre général.
Clark Nelson mentionne avoir oublié de consulter LEWG à propos de l'ordre relatif des paramètres de type size_t et align_t dans une signature de fonction, mais s'attend à des réactions si la proposition actuelle ne sied pas.
Jens Maurer fait remarquer que certains autres passages du texte normatif devraient faire référence à cette macro, en particulier ceux qui discutent de « suitably aligned storage ». L'idée est de distinguer le normatif, qui touche CWG, des trucs qui servent à l'écriture de la bibliothèque. Clark Nelson en discutera avec LWG.
Mike Miller mentionne qu'un choix terminologique malheureux dans le texte proposé rend les types sur-alignés immortels. Clark Nelson s'interroge sur la possiblité de cas de sous-alignements, mais John Spicer fait remarquer qu'il est illégal de donner à un type un alignement inférieur à son alignement naturel. Clark Nelson explique son intention et propose une formulation qui convienne mieux, tenant compte de l'alignement du premier attribut du type. L'intention ici est de réduire les cas inutiles de comportement indéfini. Clark Nelson dit que l'une des idées à exprimer ici est ce qui se produira si la mémoire sous-jacente à un objet est allouée par une fonction tenant compte de l'alignement mais libérée par une fonction qui n'en tient pas compte.
John Spicer dit ne pas être certain qu'on ait explicitement exprimé que si une classe possède un attribut d'instance qui soit suraligné, la classe est aussi suralignée. Faudra examiner cette question dans le futur.
Michael Herrick demande si on doit ajouter des mentions dans l'annexe C, portant sur la compatibilité entre les langages et les versions. Les gens dans la salle ne sont pas convaincus. On discute un peu, et on en arrive (à la suggestion de John Spicer) au constat qu'il serait préférable de le faire.
La proposition de ce trait semble simple, mais « le diable est dans les détails »; il faut exprimer correctement l'intention, et le choix des mots compte pour éviter la confusion et les cas limites. L'auteur, Mike Spencer, vient nous rejoindre.
La formulation proposée est « A contiguous-layout type is a standard-layout type for which for all values all bits in the object representation participate in the value representation ». Doit-on comprendre qu'il ne doit pas y avoir de « trous » dans la représentation, ou comprendre que chaque combinaison de bits doit représenter une entité distincte?
Mike Spencer cherche à décrire qu'il est impossible de distinguer, par exemple, deux NaN à l'intérieur des mécanismes usuels du langage. Clark Nelson mentionne la distinction entre les zéros positif et négatif des nombres à virgule flottante. Hubert Tong demande des précisions sur ce qu'on entend par « observer une différence ». Mike Spencer parle d'écrire une fonction comparant deux valeurs et vérifiant si elles sont pareilles ou non. Plusieurs font remarquer que faire un memcpy() dans une séquence de bytes non-signés et tester les bits séquentiellement est toujours possible.
Jens Maurer suggère deux correctifs : le nom devrait être ajusté (Mike Spencer dit être d'accord, et attend des recommandations d'autres groupes de travail), et discuter de l'impact des Bit Patterns sur le sens de ce trait.
Jens Maurer se questionne sur l'impact éventuel de ce trait pour détecter la présence de padding dans un agrégat.
Hubert Tong fait remarquer que les échanges ont débuté avec le concept de comparer deux objets, mais portent maintenant sur l'impact de l'affectation (qui devrait permettre une comparaison bit à bit avant et après). Hubert Tong estime que c'est la même situation pour la comparaison de deux bytes bruts. Mike Miller vérifie auprès de Mike Spencer si la sémantique à laquelle nous semblons arriver rejoint son intention.
On confirme que pour les nombres à virgule flottante, sur des systèmes implémentant IEEE 754, nous aurons ceci :
float f0 = ...;
float f1 = f0;
assert(memcmp(&f0, &f1, sizeof(f0)) == 0);
Ce que Mike Spencer souhaite de ce trait est qu'il permette de vérifier que cette situation (comparabilité bit à bit avant et après affectation) tienne pour un type T donné.
Jens Maurer demande si is_trivially_copyable_v<T> est un prérequis pour ce nouveau trait, et si on peut faire l'économie d'une référence à memcmp() pour cette raison. On semble penser que oui.
Reste à trouver un nom. Hubert Tong estime que cette fonctionnalité est décrite par CWG, mais que le nommage revient à LWG. John Spicer suggère is_byte_hashable, mais comme le fait remarquer Hubert Tong, ceci décrit surtout un cas d'utilisation. Un nom tel que is_not_padded ferait de même. Jens Maurer mentionne bits_matter un peu à la blague.
On a l'idée et une proto formulation. Hubert Tong aidera Michael Spencer pour la terminologie. Faisal Vali suggère d'ajouter un exemple de cas d'utilisation pour en comprendre l'utilité.
Clark Nelson demande si un trait dépendant de l'implémentation satisfera les programmeuses et les programmeurs. Hubert Tong indique que c'est à LWG de déterminer si cette métafonction est un point de personnalisation. On reverra Michael Spencer demain pour une terminologie retouchée.
On prend une brève pause vers 15 h 11 plutôt que 15 h 15 car nous avons commencé tôt. Je vais aux nouvelles pour voir si LWG approche du dossier de Brent Friedman. Il se trouve que la rencontre conjointe de LWG et LEWG semble destinée à se poursuivre plus longtemps qu'initialement prévu (Beman Dawes était en train de discuter du design du Caching des dossiers dans les outils de <file_system> quand je suis passé). Je suis allé voir Brent Friedman pour lui indiquer où je suis, question qu'il vienne me chercher s'ils se rendent à sa proposition dans le temps qui reste cet après-midi.
Je me suis arrêté devant les grignotines proposées à la pause : des shooters de smoothie à la mangue (mioum!), des petits morceaux de gâteau aux carottes (re-mioum!) et le combo noix et fruits séchés typique de ces rencontres (note : les noix sont non-salées, une bonne idée selon moi, surtout avec du café). J'en ai profité pour saluer Faisal Vali, car nous n'avions jamais au la chance d'interagir autrement que par voie écrite dans le passé. Un brillant bonhomme.
Richard Smith revient parmi nous. Il a entre autres un retour d'EWG pour la question de l'interaction entre la terminologie du constexpr if et les règles de capture des λ génériques : ils ont accepté (« reluctantly ok » est le terme utilisé) le fait qu'il faut retravailler les règles de capture des λ génériques, et ont « nominé » Faisal Vali pour étudier la question (on se bidonne un peu).
Mike Miller indique qu'on peut donc aller de l'avant pour le texte de D0135r1: Wording for guaranteed copy elision through simplified value categories, et en faire la proposition P0292R2. Nous amènerons cette proposition en plénière vendredi.
On revient à D0135r1: Wording for guaranteed copy elision through simplified value categories dû au retour de Richard Smith.
Jason Merrill arrive (il vient tout juste d'arriver en ville et vient nous rejoindre).
Mike Miller fait remarquer que dans certaines circonstances, un recours à typeid peut mener à la matérialisation d'une temporaire. Richard Smith indique qu'il a écrit la proposition sous cette forme pour éviter un changement de comportement (on aurait pu omettre cette matérialisation, mais il y aurait alors eu un changement de comportement inattendu). Mike Miller suggère de clarifier la relation entre une matérialisation et un opérande non-évalué, peut-être dans une note non-normative. Jens Maurer fait remarquer que les opérateurs de conversion maison sont déjà sollicités dans le contexte d'un recours à sizeof. Mike Miller clarifie la confusion à ses yeux : il est important qu'il soit clair aux yeux de toutes et tous que la matérialisation n'implique qu'un aspect sémantique, pas la création d'un objet. Le problème est que le texte est déjà un peu dense... On décide de ne pas procéder.
Faisal Vali fait un lien entre la nouvelle définition de glvalue proposée par Richard Smith et le texte normatif existant, §1.9 qui parle de value computation et de l'identité d'un objet, qui équivaut selon lui à la détermination du lieu d'un objet. On convergerait vers une formule unifiée qui décrit « identité » sur la base de « occuper le même lieu ».
Dinka Ranns suggère une retouche de lisibilité dans une clause complexe. On retravaille la formule, effectivement plutôt aride. Ceci implique quelques échanges sémantiques sur ce que fait une expression (en tant qu'entité active ou en tant qu'effet), un choix de verbe qui ne convient pas à tous les gens présents.
Je dois prendre des notes sur le Wiki collectif car Jens Maurer quitte la pièce vers la rencontre de LWG et LEWG pour discuter de la terminologie des opérateurs de comparaison générés par défaut; il est 16 h 12. À la blague, Jens Maurer nomme « ELEWG » la combinaison étendue de ces deux groupes.
Ce qui suit est une adaptation brève et traduite librement de ce que j'ai consigné au Wiki en son absence, ce qui explique la forme plus succincte.
Mike Miller demande si nous avons une forme de consensus, mais ce n'est pas ce qui ressort des réactions des membres du groupe alors les travaux se poursuivent.
Hubert Tong fait remarquer que les séquences implicites de conversion semblent se multiplier hors de leur contexte traditionnel qui est la résolution des surcharges. Il fait remarquer que ces séquences sont susceptibles de générer des objets, ce qui peut être inapproprié. Hubert Tong invite à la réflexion sur cette question, n'ayant pas la solution dans l'immédiat.
Mike Miller demande si §13.3.3.1 est suffisamment général dans sa forme actuelle. Hubert Tong explique qu'à son avis, cette section se généralise mal.
Dinka Ranns est d'avis que §8.5.4, puce 3.8 se lit mal. Richard Smith demande s'il serait préférable d'utiliser une forme passive, ce que préfère effectivement Dinkka Ranns, mais elle indique sa préférence pour une reformulation de la puce entière.
Hubert Tong se dit inconfortable avec les formules qui laissent entendre que les prvalue sont des entités actives. Il se dit d'avis que parler alors de « prvalue expressions » indiquerait plus clairement l'intention.
Dinka Ranns se dit quant à elle inconfortable avec le recours aux crochets(les [ et les ]) dans un texte normatif, dans le sense où cela laisse à son avis un doute sur le côté normatif (ou non) du passage ainsi encadré. Elle indique qu'il s'agit d'une remarque générale, qui pourrait être débattue à un autre moment. John Spicer parle de ce texte comme de « notes normatives ». Jonathan Caves indique que le standard de C utilise aussi cette forme.
Hubert Tong demande si le texte et l'exemple de §12.1 ont été discutés dans EWG. Richard Smith dit non, mais estime ce passage nécessaire à l'ensemble de la proposition. Roger Orr suggère qu'il soit nécessaire malgré tout de passer par EWG dû plus spécifiquement aux changements dans §12.1 p. 12. Richard Smith pense qu'il s'agit plus d'un DR. Mike Miller indique alors que la procédure serait de supprimer les changements apportés à changements dans §12.1 p. 12 puis d'écrire un DR en indiquant ces changements à titre de proposition de résolution du problème. Richard Smith est d'accord.
Nous amènerons cette proposition en plénière vendredi.
L'idée des variables inline est d'avoir des variables globales qui sont visibles de plusieurs fichiers sources sans générer de violations d'ODR. Une déclaration comme celle des variables static mais un comportement à l'édition des liens qui rappelle celui des variables extern.
J'ai manqué plusieurs échanges (mineurs, à mon avis, heureusement!) portant sur la forme du texte mais pas vraiment du fond, car je me chamaillais avec le formatage du Wiki, des titres et des liens. Faut pas se tromper car cet outil sert aussi aux autres groupes lorsqu'ils souhaitent suivre nos propres travaux.
Nous amènerons cette proposition en plénière vendredi.
Jens Maurer revient vers 17 h et hérite de mon formatage pas terrible de
Wiki; j'ai fait mon possible dans les circonstances... Il me remercie de
lui redonner le contrôle du Wiki et on se bidonne un peu .
Faisal Vali mentionne que le texte est un peu... brusque, invitant essentiellement les gens à lire la totalité du standard pour comprendre ce dont il en retourne. Les sections vers lesquelles §1.8 p. 1 mène sont vastes et il n'est pas immédiatement clair à partir du texte quelles sont les parties importantes.
Jason Merrill suggère une clarification sur le passage qui décrit quand un pointeur devient invalide. Richard Smith ajuste.
Hubert Tong demande une clarification sur le fait qu'un objet offre un espace d'entreposage pour un autre (provides storage for...). Ce passage de §1.8 p. 2 discute du début et de la fin de la vie d'un objet, et soulève la question de l'arithmétique de pointeurs de bytes (des char*). L'exemple présenté dans le texte est :
template<typename ...T>
struct AlignedUnion {
alignas(T...) unsigned char data[max(sizeof(T)...)];
};
int f() {
AlignedUnion<int, char> au;
int *p = new (au.data) int; // OK, au.data provides storage
char *c = new (au.data) char(); // OK, ends lifetime of *p
char *d = new (au.data + 1) char();
return *c + *d; // OK
}
Jens Maurer offre un questionnement sur la durée de vie d'un tableau servant de substrat à une structure de données plus complexe (on pense à std::vector ici). L'échange fait ressortir que la terminologie du static_cast dans le standard est incorrecte pour les conversions de pointeur entre un type Standard Layout et le type de son premier attribut d'instance.
Hubert Tong trace une distinction entre pointeur et adresse (les deux définitions ne sont pas identiques). Il mentionne que décrire la valeur d'un objet comme l'ensemble de ce qu'il contient ou peut représenter règlerait une partie des préoccupations normatives mises de l'avant ici.
Mike Miller demande si nous sommes en mesure de trancher sur cette proposition. Jason Merrill demande si Richard Smith a besoin d'y réfléchir en soirée, mais ce dernier pense pouvoir faire les dernières retouches immédiatement. Jens Maurer questionne la formulation choisie pour déterminer si une valeur de pointeur est la même avant et après une manoeuvre. On échange, mais ça semble tenir.
Richard Smith indique que LWG a demandé de faire en sorte que std::launder() ne puisse pas obtenir de l'espace d'entreposage a priori inaccessible. Le texte a été ajusté.
Richard Smith suggère qu'on présente le tout devant LWG avant d'officialiser le tout. On clôt l'après-midi à 17 h 30.
Roger Orr apporte le badge d'Aaron Ballman, qui ne peut être parmi nous, et prend une photo pour lui in absentia. Dans l'ascenseur me ramenant à ma chambre, je croise John Lakos avec qui j'ai un bref échange sur le fait qu'il soit impossible d'utiliser l'ascenseur ici sans avoir en mains une carte servant de clé pour une chambre, même pour sortir de l'ascenseur une fois la porte refermée si l'ascenseur a déjà atteint sa « destination finale » (c'est un comportement étrange pour les nord-américains que nous sommes).
Za et Cindy dorment, ayant eu (je présume) une grosse journée de plein-air. Je planifiais faire un bref somme avant le souper et le Town Hall Meeting ce soir, mais finalement, le temps a filé et quand j'ai regardé l'horloge, il était déjà 19 h 20 ici et nous avions moins de 40 minutes pour faire quelques courses et s'assurer que je mange une bouchée.
Heureusement, mes compagnes de voyage avaient fait les efforts de reconnaissance des lieux plus tôt aujourd'hui, donc nous avons pu être efficaces. Dans les temps, nous avions acquis des « gougounes » pour Za, qui voulait profiter de la piscine de l'hôtel, quelques bouteilles pour profiter des longues soirées (de la bière locale entre autres, pas vilaine), une bouchée pour moi, etc.
Nous sommes revenus à l'hôtel pour 20 h 5. J'ai mangé mon sandwich (qui avait étrangement la même saveur de sauce dijonnaise que ma pizza de la veille), goûté au poisson local de Za et Cindy (il leur en restait un peu de leur dîner), puis je me suis dirigé vers le lobby de l'hôtel.
Arrivé au lobby, nous étions nombreux (la vaste majorité des participants à cette rencontre du WG21 a répondu présent, je dirais). Vers 20 h 15, Jens Maurer (qui nous a servi de guide ce soir) nous a donné le signal et nous a conduit vers l'hôtel de ville, à quatre ou cinq coins de rue de l'hôtel (vraiment pas loin).
J'ai profité de cette marche pour prendre des nouvelles de Brent Friedman, qui m'a avoué avoir trouvé sa première journée parmi nous à la fois intellectuellement stimulante et ennuyante, ce que je peux comprendre : c'est à la fois du travail de grande rigeur et un effort d'analyse de sombres détails, ce qui recoupe de part et d'autre ses impressions. Je pense qu'il est habitué à ce que les choses bougent plus rapidement, à prendre des risques quitte à se tromper, mais la tolérance au risque d'un groupe comme le nôtre, étant donné les conséquences d'une erreur, est beaucoup moins grande (sans être nulle, car nous prenons régulièrement des risques; c'est l'ampleur des conséquences qui frappe dans notre cas).
L'hôtel de ville est un joli bâtiment. Nous sommes entrés et nous sommes regroupés dans un grand hall jusqu'à ce qu'on nous signale de gravir les escaliers qui mènent à l'étage supérieur, où nous avons été accueillis par une colonne de dignitaires locaux, dont une majorité de femmes (les trois quarts) à qui nous avons serré la main individuellement. Dans la salle de réception, un petit banquet (de qualité : du très bon saumon, des salades, des terrines de légumes, des macarons, quelques fromages, des légumes racines, etc.) nous attendait, de même qu'un mousseux et du vin en quantité.
Les dignitaires qui nous ont accueillis ont tour à tour tenu quelques discours sympathiques, mettant un peu en relief leur relation (souvent ténue, mais c'est l'effort qui compte) avec le monde de la programmation et (surtout) les vertus de leur ville. Après plusieurs discours et quelques toasts, les gens ont grignoté, bu et (dans certains cas, particulièrement Gor Nishanov) joué du piano dans le coin de la pièce.
J'ai passé le plus clair de mon temps à bavarder avec le sympathique Maxim Kartashev, qui habite St-Petersbourg mais travaille pour Oracle, une firme américaine. J'ai aussi eu le plaisir de prendre des nouvelles de Jonathan Wakely, qui a vécu le mariage d'un ami en Inde peu après notre dernière rencontre à Kona et de Gor Nishanov (très brièvement). Outre quelques échanges avec une dignitaire locale, où j'ai pu lui donner mon impression (fort positive) des lieux et de l'accueil, j'ai passé beaucoup de temps à échanger avec Hubert Tong et Maxim Kartashev sur des sujets d'ordre politique et technique, en vue des votes de vendredi et de samedi. Ce fut intéressant et instructif. Mon idée n'est pas faite sur la plupart des sujets, mais comprendre les enjeux du point de vue des autres permet de définir une perspective plus riche sur les sujets (je suis, en soi, bon public : en tant que programmeur, j'ai envie d'avoir les nouveaux joujoux qui sont proposés, du moins pour la plupart d'entre eux, même si certains me posent problème et si je vote aussi souvent « contre » ou « tiède » que « pour » en pratique).
Nous avons un immense dossier entre les mains, et une immense responsabilité. En votant sur ce que sera C++ 17, nous donnons une forme au futur proche qui peut aider la créativité des gens mais qui peut aussi leur compliquer singulièrement l'existence, ce qui – en pratique – affectera la vie de presque toutes les personnes sur la planète qui utilisent des appareils électroniques, souvent à leur insu. Ceci a deux grands impacts :
J'ai marché vers l'hôtel avec Nicolai Josuttis, qui est visiblement très préoccupé par ce qui se passe du côté de la bibliothèque standard, en particulier pour ce qui a trait à l'impact des nouvelles mécaniques du langage sur l'existant. Il m'a exprimé son opinion (qu'il n'est pas le seul à porter) que pour plusieurs propositions proches de l'adoption, il reste encore beaucoup d'inconnues.
À l'hôtel, j'ai dégusté une des bières locales achetées plus tôt, retourné quelques courriels et écrit quelques mots sur le présent document avant d'aller m'étendre, un peu avant minuit. Le soleil est encore visible dans le ciel.
Truc amusant au réveil quand on a une routine de démarrage de journée : cette routine est fortement affectée par le décalage horaire, surtout quand notre travail repose en grande partie sur les médias électroniques.
Dans mon cas, au Québec, le réveil démarre (une fois la routine du matin elle-même démarrée : douche, mettre la percolation du café en marche, ce genre de truc) avec la lecture de certains sites (blogues, bandes dessinées, nouvelles) et le retour des courriels. Ensuite, un coup d'oeil rapide au fil Twitter et on se met en marche (gestion des enfants en vue de l'école ou de la garderie, puis le boulot rémunéré). En proportion, la partie « lecture des sites » est un peu plus longue que la partie « Twitter » car plusieurs sites ont un rythme de mise à jour régulier (quotidien, aux deux jours, trois fois par semaine, etc.) et car, je le constate, je suis plus de gens sur Twitter dans des fuseaux horaires connexes au mien que de gens plus loin (Europe, Asie, Océanie...). En Finlande, les sites que je lis quotidiennement tendent à ne pas avoir changé de contenu entre le moment où je me couche et le moment où je me lève, du moins pas de manière importante, alors que le volume de tweets est doublé (les gens que je suis sont productifs pendant que je dors, étant pour leur part en plein jour). Au total, le volume et le même mais la distribution est radicalement différente.
Il me reste quelques propositions à lire pour être prêt en vue de la journée, alors on se met en marche...
Quand Za et Cindy se sont levées, nous sommes allés cueillir le déjeuner dans un petit commerce en face de l'hôtel, à l'autre extrémité du marché public. Des pâtisseries qui semblent très bonnes (je confirme pour avoir goûté un morceau : salissant mais délicieux!) et des mets locaux (avec du saumon frais, des herbes, des oignons) nous ont servi de déjeuner au retour à l'hôtel.
Une bouchée pour moi, puis au boulot.
À 8 h 30, je suis à LWG pour assister (entre autres) à la présentation de Brent Friedman, tel que promis. Il se trouve que Brent a vécu une expérience bien connue dans le milieu... Dans ses mots, « I've been Lakos'ed » (en référence à ce moment où John Lakos entraîne un individu qui ne le suspecte pas dans une dérive de consommation de boisson). Il s'en remettra, j'en suis sûr.
Il y a moins de gens qu'à l'habitude à LWG ce matin du fait qu'une rencontre conjointe de SG1 et de LEWG se tient non-loin, avec un débat houleux autour de la proposition du type std::joining_thread de Ville Voutilainen, et du texte à l'effet que ce type risque de mener à des interblocages et ne devrait pas être standardisé par Detlef Vollmann.
En particulier, Vicente J. Botet Escribá devait terminer une présentation mais est absent, nous passons donc à la partie LWG de la proposition de Clark Nelson, à la suite de ses représentations devant CWG hier.
Il semble que la personne prenant habituellement des notes sur le Wiki de LWG soit absente. Marshall Clow demande un volontaire en me fixant des yeux, alors j'ai pris le relais. Pour cette raison, ce qui suit se base sur ce que j'ai pris comme note en cours de route est est plus succinct que ce que j'aurais écrit en temps normal.
Les travaux ont commencé vers 8 h 30. Marshall Clow accueille les gens présents et leur rappelle que nous sommes ici pour examiner le texte des propositions, pas pour mettre au point de nouveaux trucs.
Clark Nelson réfère les gens présents au Wiki de CWG, qui contient la version la plus récente de son texte étant donné les changements apportés hier. Il indique que CWG a recommandé d'indiquer les changements de comportement à l'annexe C du standard. Il indique aussi que LEWG et CWG ont tous deux suggéré des formulations pour la macro prédéfinie; en fait, selon Clark Nelson, outre l'ajout de la macro, peu de choses ont vraiment changé depuis Jacksonville.
Marshall Clow demande si LWG a travaillé la terminologie avec Clark Nelson, mais ce dernier dit ne pas en avoir le souvenir. Marshall Clow dit qu'il faut s'y mettre, et demande d'avoir un bref survol du dossier. Clark Nelson explique : si un type est aligné autrement que selon son alignement naturel, et devient par le fait-même suraligné, il faut que les fonctions d'allocation (les variantes de new et de delete) retournent aussi des objets alignés.
Clark Nelson ajoute que ceci a un impact malheureux sur le nombre de fonctions d'allocation à surcharger, pour qui s'en préoccupe. Marshall Clow demande si cela affecte à la fois les variantes de new and delete de manière symétrique, mais Clark Nelson explique qu'il y a des cas légitimes pour avoir recours à une fonction de libération dont la signature ne rejoint pas celle de la fonction d'allocation correspondante.
Clark Nelson explique qu'avec le texte actuel du standard, le rôle exact du placement new est quelque peu ambigü. Il dit avoir pris un peu de temps au passage pour nettoyer la terminologie existante. Marshall Clow lui demande si le terme « non-allocating form » pour décrire ce mécanisme est sa propre invention, ce que Clark Nelson confirme.
P.J. Plauger : « this gives me "the willies" ». Il nous demande comment ces nouveaux mécanismes interopéreront avec les allocateurs polymorphiques. En effet, les allocateurs ne se préoccupent typiquement pas de considérations d'alignement en mémoire, mais les allocateurs polymorphiques sont supposés interfacer directement avec les fonctions d'allocation. Clark Nelson dit ne pas bien connaître les allocateurs polymorphiques; son intention est de rester au deuxième niveau le plus bas dans les mécanismes de gestion de la mémoire, dans le seul but de bien supporter l'allocation de mémoire pour les types suralignés. Il dit comprendre qu'un allocateur est typé, et qu'il devrait donc être en mesure de déduire l'alignement du type sous sa gouverne. P.J. Plauger se dit d'accord avec sa démarche, mais constate qu'elle met en relief un problème de fond avec les ressources polymorphiques.
Nathan Myers est d'avis qu'il faut tenir Pablo Halpern au courant des développements dans ce dossier; selon lui, le plus important est que les deux approches (fonctions d'allocation pour types suralignés et allocateurs polymorphiques) ne soient pas fondamentalement en désaccord.
Marshall Clow remercie Clark Nelson pour avoir utilisé may plutôt que can à certains endroits. Clark Nelson avoue avoir fait quelques retouches imprévues au passage.
Clark Nelson demande aux membres de LWG s'ils ont des recommandations à faire quant à l'ordre des paramètres pour ces nouvelles déclinaisons des fonctions d'allocation. Marshall Clow répond qu'il peut dicter l'ordre qui lui semble pertinent s'il a une vision claire. Clark Nelson indique qu'il a perçu un faible consensus dans CWG quant à l'ordre qu'il a choisi jusqu'ici.
Geoffrey Rohmer fait remarquer que certaines fonctions placent la taille en bytes avant l'alignement en mémoire et d'autres font l'inverse. Clark Nelson explique que cela dépend de la nature de la fonction (variante de new ou de delete) et dit que dans certains cas, la taille n'est qu'indicative. P.J. Plauger est d'avis que nous devrions viser une approche uniforme à l'ordonnancement des paramètres. Clark Nelson rappelle qu'il a inventé ces nouveaux mécanismes avant l'avènement des déclinaisons de delete acceptant une taille en paramètre, ce qui a forcé chez lui quelques retouches. Il dit ne pas être opposé à un changement de l'ordre des paramètres; selon lui, avec l'avènement de C++ 17, on pourra faire des correctifs de dernière minute sur la base de l'expérience.
Walter E. Brown : « consistency: good. Inconsistency: bad ». Clark Nelson : « we have to choose on what to be consistent ». Walter E. Brown : « I did not mean to be inconsistent with that »
Marshall Clow demande si quelqu'un dans la salle voterait contre la proposition sur la base de l'ordre dans lequel apparaissent les paramètres. Silence...
Clark Nelson demande si le prospect de livrer ces nouveaux mécanismes avec C++ 17 semble choquant aux gens présents. Marshall Clow dit qu'à son avis, on parle d'un changement significatif. Clark Nelson demande s'il serait préférable qu'il fasse les correctifs pressants à la proposition pour livrer dans le CD, puis corriger les erreurs restantes par la suite. Marshall Clow répond « oui ».
Marshall Clow demande si CWG a passé la terminologie en revue. Clark Nelson répond que oui, mais qu'il doit retourner devant CWG pour valider des retouches. Marshall Clow émet le souhait de limiter le nombre de trajets aller/ retour entre les deux groupes.
Clark Nelson : §3.7.2 p. 3 contient des éléments qui affectent en priorité la bibliothèque standard. J'en ai retiré des éléments qui me semblaient redondants et qui apparaissaient dans §18.6 du fait qu'ils me semblaient plus près des clauses de la bibliothèque que de celles du coeur du langage.
Clark Nelson : §3.11 p. 3 donne la définition de extended alignment et a été ajusté pour tenir compte de __STDCPP_DEFAULT_NEW_ALIGNMENT__. Certaines retouches terminologiques mineures suivent.
Walter E. Brown : dans §5.3.4 p. 22 apparaît une nouvelle phrase avec un paramètre size. Devrait-on expliciter std::size_t?
Clark Nelson : oui. Devrais-je reformuler? Marshall Clow : si tu le fais, vise une conformité de forme avec les passages similaires du standard.
Clark Nelson : actuellement, les fonctions de libération de mémoire acceptent void* ou void*, size_t. La terminologie existante parle de « the two forms », ce qui devient caduque avec les versions tenant compte des besoins en termes d'alignment.
Walter E. Brown fait un tour rapide des formules existantes et dit avoir une préférence légère pour celles qui expriment directement le type. Il y a un assentiment général dans la salle.
Marshall Clow recommande un autre passage par CWG , question de prudence.
Clark Nelson demande s'il devrait écrire std::size_t ou se limiter à size_t. Walter E. Brown suggère de se fier sur la vision de CWG . Marshall Clow jette un coup d'oeil aux exemples existants et constate le recours à std::. Sur cette base, Walter E. Brown recommende des changements semblables dans tout le document.
Clark Nelson dit trouver les phrases qui parlent de « functions with no alignment parameter » un peu lourdes. Walter E. Brown suggère d'insérer un nom pour cette famille de fonctions tôt dans la proposition, puis de s'en servir. Clark Nelson dit qu'il essaiera.
Walter E. Brown demande s'il existe une terminologie pour établir qu'un usager doit suppléer la forme de delete corresponmdant à chaque new surchargé. Marshall Clow pense que si.
Patrice Roy demande pour quelle raisons les modalités de passage de paramètres varient entre nothrow_t (passage const&) et align_t (passage par copie). Clark Nelson répond qu'il s'agit d'une convention.
Axel Naumann demande s'il y avait un requis à l'effet que la taille en bytes soit un multiple de l'alignment. Clark Nelson dit que ce questionnement vient de CWG , mais pourrait être superflu. Il se demande s'il serait raisonnable de l'éliminer. Marshall Clow demande si cette clause, ou son absence, affecte le coeur du langage? Clark Nelson est d'avis que cette restriction est destinée aux usagers, mais ne pense pas que cette restriction soit raisonnable en général.
Marshall Clow demande si quelqu'un s'oppose à la suppression de cette contrainte; un silence s'ensuit. Marshall Clow dit qu'à son avis, LWG vient de s'exprimer, et que Clark Nelson peut retourner devant CWG .
Marshall Clow recommande quelques formulations et constate des accrocs terminologiques dans le texte existant. Il suggère qu'une proposition de Walter E. Brown serait la bienvenue pour entreprendre un grand nettoyage.
Axel Naumann demande ce qui se produira si une plateforme ne supporte pas l'allocation. Clark Nelson explique qu'il s'agit d'un mécanisme rappelant la surcharge, et rappelle que la forme « ancienne » demeure à titre de backup. Axel Naumann ne voit pas cela dans la terminologie. Clark Nelson dit que cette terminologie n'est pas dans la section du standard qui discute de la bibliothèque. Walter E. Brown pense qu'une note explicative serait pertinente.
Geoffrey Rohmer : dans §18.6.2.1 p. 9, nous utilisons le terme « corresponding non-placement function », mais est-ce raisonnable dans le contexte? Clark Nelson : la définition du placement new mérite d'être retouchée.
Axel Naumann : dans §18.6.2.2, le cas où le pointeur est nul n'est pas couvert. Clark Nelson : la terminologie de l'opérateur new dans ses diverses formes telles qu'operator new[] n'est pas homogène. Je n'étais pas certain jusqu'où je pouvais aller. Axel Naumann : j'ai en tête ces passages où nous indiquons que le paramètre passé à delete doit provenir d'un appel antérieur à new. Nous sommes parfois explicites, et parfois nous ne le sommes pas. Clark Nelson : que suggérez-vous? Marshall Clow : je pense qu'il faudrait dupliquer la formule du paragraphe 12 aux paragraphes subséquents.
Clark Nelson : l'énoncé supprimé dans §3.7.4p3 s'appliquait-il à la bibliothèque standard, aux usagers ou à ces deux catégories? Alisdair Meredith : cet énoncé est étonnant dans le contexte où il apparaissait. Clark Nelson : je ne veux pas que tout soit parfait, mais je veux que ce soit correct. Walter E. Brown : je pensais que limiter ces remarques aux sections portant sur la bibliothèque standard suffirait mais je n'en suis plus convaincu. Je préférerais qu'elles soient dans la section sous l'égide de la bibliothèque standard si c'était possible. Axel Naumann : cela signifierait qu'il s'agit d'un requis imposé aux usagers appelant la fonction, alors que l'indiquer dans §3 change la perspective. Daniel Krügler : nous pouvons y aller avec §3.7.4. Marshall Clow : il est amusant de constater que les usagers appellent rarement directement les fonctions d'allocation.
Alisdair Meredith : cette section ne parle pas des mécanismes d'allocation et ne règle pas notre problème. Walter E. Brown : je ne pense pas que ce problème soit celui de Clark Nelson. Clark Nelson : j'ai modifié ce passage car il ne fonctionnait pas à mes yeux; je ne suis pas prêt à le remettre tel quel.
Alisdair Meredith : je préfère voir les requis dans les sections touchant à la bibliothèque standard. Marshall Clow : devrait-on dupliquer le paragraphe 12? Alisdair Meredith : oui.
Marshall Clow : je préferais aussi une terminologie plus générale, mais je ne veux pas que cela soit la responsabilité Clark Nelson. Clark Nelson : je peux le faire mais j'ai besoin d'aide. Marshall Clow : je pense qu'on veut prendre les pragraphes 12 et 14 pour les dupliquer aux endroits appropriés. Alisdair Meredith : c'est aussi mon souhait. Walter E. Brown : j'aimerais que Clark Nelson prenne les décisions, étant l'auteur. Daniel Krügler offre son aide.
Marshall Clow : et les tableaux? Clark Nelson : je m'attends à des changements semblables.
Clark Nelson : je veux signaler une nuance dans le cas des tableaux, où l'on parle de « an object of that size or smaller » dans un cas mais pas dans l'autre. J'ai pris la liberté de les harmoniser. Marshall Clow : d'où venaient ces différences? Clark Nelson : je ne sais pas, mais ça me semblait suspect.
Clark Nelson : je me demande si la bibliothèque standard a le droit de supposer qu'un alignement pour un objet de quatre bytes ne peut être plus grand que quatre. Je pense qu'il ne s'agit que de « comment les choses sont », que la pratique suppose que l'alignement de base rejoint la taille de l'objet.
Marshall Clow : j'ai fait un peu de recherche et les requis actuels (et disparates) sont formulés tels quels depuis au moins vingt ans. Ça me rend plus frileux à l'idée de les changer... Des échanges s'ensuivent sur la relation entre la taille d'un objet en mémoire et son alignement naturel, de même qu'avec la taille d'un tableau pour assurer le sain alignement des éléments aux positions non-nulles.
Clark Nelson : le passage « smaller » indique que si on essaie d'aligner un objet sur un seuil de moins que alignof(double), alors l'implémentation peut supposer que l'on n'a pas alloué un double.
Alisdair Meredith : je préfèrais qu'on ouvre un « issue » pour traiter ceci dans l'ordre des choses.
Axel Naumann suggère de simplifier la terminologie de la note en bas de page 224. Geoffrey Rohmer est d'accord. Marshall Clow recommende une harmonisation de la terminologie des diverses fonctions d'allocation
.Marshall Clow suggère que nous prenions une pause. Il est 10 h 17. À la pause, je jette un coup d'oeil sur le Wiki de SG1. Il semble que joining_thread n'ait pas obtenu le consensus requis ce matin. La salle de LWG se remplissait rapidement en fin de première partie de la matinée, suggérant que cet épineux dossier ait été traité.
Le goûter à la pause comprenant des bouchées de mousse de saumon sur croûtons noirs (du pumpernickel ou une proche variante) et des sandwichs sur très petits pains multigrains en forme de coeurs, avec jambon et marinades. J'ai eu un bref échange avec Daniel Krügler qui est un très sympathique monsieur.
Pendant la pause, j'ai reçu un courriel d'ISO indiquant que le WD pour les modules a été approuvé.
Clark Nelson : ce qui me préoccupe est que le texte ajouté à l'annexe C est complètemement nouveau; je suis son seul lecteur jusqu'ici.
L'annexe C du standard dénote principalement les incompatiblités entre la version courante du langage C++ et la précédente, de même que celles entre les langages C++ et C. Le nom « annexe C » est un concours de circonstances et n'a rien à voir avec les noms des langages.
Casey Carter : si on le prend du point de vue de la compatibilité avec l'existant (backwards compatibility), toutes les implémentations d'allocateurs deviendront non-conformes après ce changement. Clark Nelson : elles seront non-conformes, mais seulement sur des types suralignés. C'est un cas très « niché », cela dit, et les allocateurs existants ne fonctionnent pas dans ces cas pour le moment de toute manière.
Marshall Clow : je pense qu'il est temps de faire les ajustements recommandés, de revenir devant CWG, puis de revenir nous voir pour ficeler tout ça.
On tient un vote pour déterminer s'il y a consensus de LWG pour recommander l'adoption de ce nouveau mécanisme pour C++ 17 suite à une application satisfaisante des changements; le vote est nettement faborable.
Clark Nelson demande quand LWG compte examiner la proposition à l'effet de réviser la référence normative au langage C, qui pointe actuellement vers C99 alors que la plus récente version de ce langage est C11. Marshall Clow dit que ce sera fait plus tard aujourd'hui ou tôt demain.
Brent Friendman explique que cette proposition amène neuf algorithmes distincts pour implémenter efficacement des conteneurs; l'idée est d'offrir une gamme de fonctions standard pour aider celles et ceux qui n'ont pas recours aux allocateurs standards. Sa proposition a une (faible) dépendance envers issue 2598 à l'effet d'interdire de prendre l'adresse d'une variable temporaire; si cette question n'est pas résolue, sa proposition ne tombe pas, mais on pourrait abuser certains de ses algorithmes (en particulier std::destroy()) de manière accidentelle et causer des dégâts.
Nicolai Josuttis : quels sont les algorithmes de cette famille que nous avons déjà? Brent Friendman : nous avons uninitialized_copy() et uninitialized_fill(). Nicolai Josuttis : est-ce que ces algorithmes sont modifiés? Brent Friendman : non.
Marshall Clow constate que les algorithmes ont des déclinaisons munies de politiques d'exécution, ce qui permettra par exemple de les exécuter en parallèle. Brent Friendman répond par l'affirmative, et dit avoir écrit ces déclinaisons dès que les politiques d'exécution ont été acceptées pour C++ 17.
Marshall Clow demande si LEWG a approuvé les noms de ces nouveaux algorithmes, et si ces noms correspondent aux fonctions connexes des allocateurs. Brent Friendman confirme dans les deux cas.
Nicolai Josuttis n'apprécie pas l'indentation dans la proposition, et demande que les propositions doivent être bien indentées pour faciliter les revues en groupe de travail. Quelques échanges s'ensuivent. Marshall Clow indique que si cette proposition devait revenir devant LWG cette semaine, l'indentation devrait être faite de manière plus rigoureuse au préalable.
Casey Carter fait remarquer que l'une des déclinaisons de destroy() est incorrecte, un des paramètres du template étant annoté d'un && (ça ressemble à une erreur de coipier/ coller). Nicolai Josuttis note que les paramètres décrivant une séquence sont parfois nommés begin et end, et sont parfois nommés first et last. L'usage chez LWG est first et last. Casey Carter remarque une erreur typographique sur le type d'un paramètre représentant une politique d'exécution.
Casey Carter se dit inconfortable avec la terminologie utilisée pour ForwardIterator dans §20.9.12, qui diffère de celle utilisée dans §25. Brent Friendman fait remarquer que la terminologie a été prise du texte du standard. Daniel Krügler constate que les mots utilisés ici sont plus forts que ceux dans la section sur les itérateurs.
Geoffrey Rohmer constate qu'une référence à §25.1.12 devrait probablement mener vers §25.1 p12. Brent Friendman confirme. Geoffrey Rohmer suggère qu'il puisse être préférable de copier / coller la terminologie d'origine. Brent Friendman dit qu'il y a pensé mais qu'on lui a plutôt recommandé de faire une référence alors qu'il préparait la proposition. Casey Carter suggère de fusionner le nouveau passage dans §25.1. Beman Dawes dit que dans §25.1, un sous-section pourrait être ajoutée pour faciliter le référencement. Marshall Clow recommande de consulter Richard Smith, éditeur actuel du standard, car il sera de bon conseil.
Il faut savoir ici que dans le standard, les références sont à des sections plus qu'à des paragraphes de sections.
Walter E. Brown : dans la terminologie proposée, j'aimerais avoir des crochets autour des balises stables (p. ex. : [map.cons]), et je préférerais des balises stables aux numéros (p. ex. : [23.4.4.2]) qui sont susceptibles de changer. Marshall Clow : mes macros LaTeX corrigeront tout cela.
Walter E. Brown : certaines sections apparaissent dans la proposition même si rien n'a changé. Brent Friendman : c'est parce que je changeais presque tout alors...
Marshall Clow : je n'aime pas la formulation « If an exception is thrown, there are no effects » qui est incorrecte; lever une exception est un effet, après tout! Mais c'est du texte préexistant donc ce n'est pas ta faute. Brent Friendman : il y a une exception (!) à la règle dans le cas d'uninitialized_move(). Nicolai Josuttis : tu pourrais faire un énoncé général, complété par « unless otherwise specified », pour que l'exception à la règle soit la seule à être différente. Cela allégerait l'ensemble.
Casey Carter : les sections sur uninitialized_fill() et uninitialized_fill_n() ont toutes deux le même nom stable. Faut corriger ça.
Geoffrey Rohmer : les clauses « Effects » devraient s'écrire « Effects equivalent to ». Daniel Krügler suggère une formulation plus efficace. Walter E. Brown indique que l'éditeur a suffisamment de liberté pour faire ces ajustements.
Nicolai Josuttis : j'apprécierais plus de cohérence dans l'utilisation d'espacement dans les exemples de code.
Walter E. Brown : devrions-nous modifier l'ordre dans lesquels sont présentés les algorithmes destroy() et destroy_at(), du fait que destroy() utilise destroy_at()? (cela ne semble pas être une préoccupation pour la plupart des gens présents).
Marshall Clow demande où sont décrites les spécialisations parallèles. Brent Friendman dit avoir pris exemple sur les autres algorithmes, qui ne décrivent pas en détail leurs déclinaisons parallèles dans le texte du standard.
Walter E. Brown demande s'il est convenable de transtyper le résultat d'un appel à addressof() vers void* lors d'une placement new. Marshall Clow souligne qu'il s'agit de pratiques préexistantes.
Casey Carter constate que l'une des implémentations suggérées de destroy() convertit le premier compteur en void dans son incrémentation alors que l'autre fait de même avec le second compteur. Il préférerait une présentation plus cohérente.
Geoffrey Rohmer fait remarquer qu'il est d'usage dans le standard d'utiliser explicitement std:: pour move() et forward().
Daniel Krügler remarque un paramètre manquant dans un template, plus précisément iterator_traits dans uninitialized_move(). Patrice Roy fait remarquer que ça ressemble beaucoup à une erreur d'HTML.
Brent Friendman souligne que la section « Remarks » des fonctions *_move() sont peut-être mal écrites. Il n'était pas certain de la formule à appliquer. Nicolai Josuttis est d'avis qu'il faudrait clarifier le fait qu'il y ait un effet sur la séquence source. Un échange s'ensuit quant à l'état de la séquence source : un objet moved-from se trouve a posteriori dans un état valide mais non-spécifié. La terminologie de l'algortihme std::move(ds,fs,dd) existant peut servir à titre d'inspiration.
Walter E. Brown fait remarquer que la terminologie dans uninitialized_move_n() devrait suivre celle utilisée dans uninitialized_move().
Walter E. Brown : je n'aime pas la notation n > 0 dans les algorithmes *_n(). C'est un commentaire général, qui ne vise pas spécifiquement cette proposition; je préférerais nettement n != 0. Brent Friendman : le problème est que Size pourrait être signé, non-signé... Marshall Clow : ...il pourrait s'agir d'un type « maison ».
Walter E. Brown : je remarque que dans uninitialized_value_construct(), nous utilisons des parenthèses plutôt que des accolades. Pourquoi? Brent Friendman : il y a une légère différence entre value initialization et aggregate initialization
Nicolai Josuttis fait remarquer des incohérences dans les exemples, anciens comme nouveaux, mais cette remarque ne vise pas non plus la proposition sur la table.
P.J. Plauger : les requis sur nos compteurs ne sont pas suffisamment spécifiés. Nous manquons de cohérence quant à la manière dont nous décrivons ces types et celle par laquelle nous les utilisons dans nos exemples.
Walter E. Brown constate que dans uninitialized_fill_n(), il y a deux opérateurs « virgule » dans une même expression, et que le transtypage en void est – raisonnablement – appliqué sur l'expression du centre.
Marshall Clow : l'algorithme uninitialized_copy_n() retourne un OutputIterator, ce qui est incorrect; nous devrions retourner une paire d'itérateurs dans de telles fonctions. Dietmar Kühl : c'est NAD; nous ne pouvons pas briser le code existant, et ceci briserait le code source. Beman Dawes : nous avons besoin d'une pratique ou d'un moment pour briser le code exitant, sinon il devient impossible de réparer le langage quand l'entropie s'installe.
Marshall Clow : est-ce que uninitialized_move_n() devrait retourner une paire d'itérateurs? Ceci ne briserait rien puisqu'il s'agit d'un nouvel algorithme. L'enjeu est de savoir s'il est préférable de poursuivre sciemment avec une approche incorrecte, par souci de cohérence interne, ou de réparer une approche brisée en acceptant une incohérence.
On tient un vote, partagé mais favorable à l'idée de retourner une paire d'itérateurs dans ce cas-ci. Les opposants sont par contre fortement opposés.
Marshall Clow dit que LWG aimerait revoir Brent Friedman avec une version révisée de la proposition. Il consulte le groupe pour savoir si le souhait est d'intégrer cette proposition, une fois corrigée, dans C++ 17. Patrice Roy indique que SG14 serait ravi d'avoir accès à ces algoirithmes. Marshall Clow dit ne voir personne s'objecter, donc l'opinion de LWG est favorable.
Walter E. Brown demande s'il serait raisonnable, en amenant cette proposition, d'amener les fonctions de type emplace du même coup. Il dit estimer qu'elles sont apparentées. Marshall Clow suggère que ce sujet soit amené pour fins de discussion dans la session de travail en soirée.
Arrive l'heure du dîner. Je mets à jour le Wiki de LWG et je fais mon possible pour que tout soit conforme à leurs usages. Il est ensuite temps de redescendre dans mon donjon sans fenêtres pour découvrir ce qui se passe à CWG. En descendant, je croise Jens Maurer qui m'a fait faire un badge plus formel, ce qui est très gentil de sa part. Je n'ai pas eu le temps de dîner, par contre, mais ça arrive.
Jens Maurer nous indique qu'une formulation du TS sur le parallélisme devrait se trouver dans C++ 17 en soi. Richard Smith demande si cette TS a été acceptée pour C++ 17; dans le cas contraire, le changement de formulation demandé ne semble pas à propos en ce moment.
Torvald Riegel vient nous rejoindre.
Jens Maurer résume : en gros, les échanges tenus à Jacksonville ont porté sur les étapes d'une exécution, en vue de clarifier clarifier quand une étape débute, quand elle se termine, ce que signifie « bloquer », etc.
Jens Maurer : nous ne sommes pas en accord sur les nuances associées au mot « bloquer ».
Jens Maurer : le TS sur le parallélisme sera-t-il basé sur C++ 17?
Torvald Riegel : je pense que oui. Ma compréhension est que P0299R1 devrait aller dans C++ 17.
Jens Maurer : sur le plan de la cohérence, il faudra alors que C++ 17 soit publié pour que le TS soit publié, sinon les définitions sur lesquelles repose le TS n'existeront pas.
Hubert Tong : il y a une distinction à faire entre P0296, qui relève de CWG, et P0299, qui est plus près des intérêts de SG1.
Jens Maurer explique sa position sur le concept de blocage, ou de bloquer, tel que décrit dans p0296. Le texte lui semble faire en sorte qu'il soit impossible de bloquer sauf en faisant un appel système. Torvald Riegel explique son intention. Il est bien sûr possible de bloquer sur un objet de synchronisation, mais ce n'est pas le seul cas possible. Jens Maurer pense que les notes sont des distractions et qu'un exemple suffirait.
Jason Merrill demande des précisions. Torval Riegel explique qu'il souhaite distinguer le blocage au niveau applicatif du blocage au niveau du système d'exploitation.
Dinka Ranns suggère une reformulation d'un passage qui laisse entendre que la bibliothèque standard fait un peu de la magie. Torval Riegel explique l'intention du texte, qui est que la bibliothèque standard suppose que le code client n'est pas écrit de manière à être brisé ou subissant des réveils intempestifs. Torval Riegel précise qu'une opération bloquante est en fait potentiellement bloquante, et peut ne pas bloquer. Il serait à l'aise avec « potentially blocking ». L'enjeu ici est qu'une entrée/ sortie bloquante est potentiellement bloquante, nous le savons tous, mais dans le texte normatif, le mot peut devenir ambigü et signifier « bloqué », ce qui entraîne de la confusion.
On discute de formulations pour décrire que les implémentations doivent
fournir des garanties de progression pour les threads, incluant
main(). On ne peut pas dire « faites-le! » dans un texte normatif,
mais on peut écrire que nous encourageons cette pratique
On amènera P0296 en plénière vendredi.
À propos de P0299, Hubert Tong pense que c'est à SG1 d'amener cette proposition en plénière, pas à CWG. L'entente (politique) cette semaine est de ne rien apporter de neuf en plénière, alors puisque SG1 a pris la décision d'aller de l'avant avec ce texte. Mike Miller se dit à l'aise d'en faire une motion de CWG, les circonstances étant particulières et le texte ayant beaucoup de vécu.
Dans le deuxième paragraphe de P0299, Richard Smith se questionne sur le sens de weakly parallel forward progress guarantees. Torvald Riegel explique l'intention derrière le passage. Richard Smith est d'accord avec la définition mais estime que l'exemple donné n'est pas pas correct. Il y a un désaccord sur le sens à donner à l'exemple. Roger Orr se dit aussi d'avis que le texte est correct mais que l'exemple ne l'appuie pas correctement. Torvald Riegel perçoit un problème dans le sens du mot « exécuter »; il y a bel et bien une différence de perception à ce sujet. On s'amuse un peu car une partie de la discussion tient à notre manière de gérer l'infini (ça se terminera éventuellement, si ça s'exécute assez longtemps; ça atteindra éventuellement tel ou tel stade). Richard Smith aime l'exemple, mais n'est pas convaincu de la cohérence de l'exemple et du texte.
Jason Merrill essaie de bien cerner la distinction entre parallel forward progress guarantee et weakly parallel forward progress guarantee. Torvald Riegel dit qu'une fois le démarrage d'un thread fait, on peut voir la situation comme un « upgrade » des conditions de progrès parallèles vers les conditions de progrès concurrentes, ces dernières étant plus fortes (le texte en fait d'ailleurs part). Jason Merrill est à l'aise avec le texte; Richard Smith demeure inconfortable avec l'exemple en tant qu'appui au texte.
Roger Orr explique sa lecture : si on a un ensemble de tâches avec garanties de progrès concurrent et qu'on en retire une à une des tâches, on obtient des garanties de progrès parallèle.
On échange un peu et on en arrive à un exemple qui satisfasse tout le monde, en ajoutant quelques qualifications aux tâches décrites dans l'exemple existant.
Roger Orr mentionne qu'un paragraphe décrivant bloquer avec garantie de progrès en termes d'une implication logique, sans véritablement définir de quoi il s'agit.
Patrice Roy est préoccupé par l'absence d'une définition normative du concept de force relative des garanties de progrès, la seule « définition » qu'il trouve dans le texte se trouvant dans une note informelle et non-normative, alors que plusieurs éléments du texte parlent de renforcer les garanties offertes (temporairement ou pas). On convient qu'il faille rendre cette définition normative pour que le texte puisse s'appuyer dessus.
Plusieurs retouches de formulation suivent pour que la lecture ne mène pas à des interprétations ambiguës. Une partie importante de ces retouches sont des cas de singulier et de pluriel. On parle de sujets extrêmement abstraits, qui recoupent la relativité et le concept même de progression chronologique concurrente et parallèle, alors ça demande un effort intellectuel important du début à la fin.
Hubert Tong demande si une implémentation a le droit de changer son choix quant au fil d'exécution qui pourra procéder si fréquemment qu'aucun progrès ne se fera. Torvald Riegel estime que non, du fait que la plus petite étape (en termes de granularité) dans la description du concept même d'exécution est une étape d'exécution, ou « execution step », et qu'on ne détermine pas qu'il y ait progression avant qu'un premier pas ait été franchi. Pour cette raison, dans le modèle préconisé, le problème soulevé n'existe pas.
Richard Smith demande si nous pouvons garantir qu'en tout temps, au moins une tâche pourra être choisie pour fins d'exécution, mais Torvald Riegel dit que non : il suffit d'imaginer un fil d'exécution alternant entre deux tâches alors qu'une des deux décide de ne jamais compléter l'une de ses étapes.
Jens Maurer demande si un ensemble de tâches offrant des garanties de progrès parallèle et dont les tâches ont effectué au moins une étape devient un ensemble offrant des garanties de progrès concurrentes. Torvald Riegel dit que le nouvel ensemble se comportera alors comme s'il offrait une garantie de progrès concurrente, en effet. Jens Maurer estime que la terminologie utilisée ne décrit pas encore vraiment l'idée que l'on souhaite y exprimer. Torvald Riegel craint que le renforcement des garanties ne semble permanent. Jason Merrill ne vise pas une terminologie qui suggère la permanence du renforcement. Dinka Ranns pense qu'on doit distinguer la situation où un ensemble de tâches offre des garanties de progrès parallèles et a fait une étape, cet ensemble n'est plus dans son état initial. Jens Maurer pense qu'on peut alors dire que les garanties de progrès concurrentes. On échange mais on semble atteindre un consensus qui a le bon côté de réduire la part de non-normatif dans le texte.
Dinka Ranns se questionne sur la définition proposée de terminaison, craignant qu'elle rende impossible de bloquer sur la fin d'un ensemble de tâches si cet ensemble est vide. Torvald Riegel indique que des attentes avec timeout sont possibles, ce qui réduit ce risque. Dinka Ranns estime que le texte peut être allégé en partie du fait que les pauses ne sont pas observables. Torvald Riegel pense qu'il est possible d'observer ces pauses par des mécanismes de bas niveau. Jens Maurer dit être d'accord avec cette position du fait que les exécutions des fonctions dans le modèle préconisé par ce texte peuvent être enchevêtrées (interleaved), ce qui est inhabituel dans le sens d'un texte normatif. Torvald Riegel pense qu'on risque de devoir revenir devant LWG pour cette partie du texte. Torvald Riegel et Jens Maurer échangent sur la relativité de « infiniment longtemps » et « très longtemps » dans une situation de blocage.
On amènera ceci en plénière vendredi.
Ouf, du gros boulot. On prend une pause vers 15 h 26. Petits gâteaux au chocolat et smoothie à la mangue; ça fait du bien étant donné que je n'ai pas eu le temps de dîner.
Hubert Tong fait remarquer que WG14 examine un document sur le préprocesseur que WG21 n'a fait qu'effleurer. Évidemment, si ce document passe de leur côté, il nous faudra se pencher dessus avec plus d'attention.
Jens Maurer est informé par EWG que les Structured Bindings sont maintenant de notre côté. Ce dossier est jugé moins important que ce qui était déjà dans le pipeline pour C++ 17 depuis Jacksonville mais plus important que ce qui ne serait pas destiné à C++ 17. Si nous parvenons à le traiter cette semaine, il se peut que cela fasse partie du prochain standard.
Nous accueillons à nouveau Clark Nelson.
Clark Nelson indique avoir fait plusieurs changements, la plupart dans la section qui tombe sous l'égide de LWG.
D'entrée de jeu, Richard Smith remarque une erreur d'ordonnancement des paramètres dans certains cas de §3.7.4 p. 2. Clark Nelson corrigera.
Clark Nelson discute d'ajustements dans la description des règles d'alignement pour les scalaires et pour les tableaux. Il explique les ajustements apportés suite aux travaux de LWG ce matin.
Clark Nelson nous guide vers §18.6.2 p. 1, et explique que LWG n'était pas d'accord avec l'ajustement suggéré par CWG à Jacksonville.
Clark Nelson indique aussi les ajustements apportés dans la représentation terminologique des tailles, soit la recommandation par LWG d'indiquer les types exacts plutôt que des abstractions.
Jens Maurer demande si LWG était à l'aise avec les changements préconisés par CWG autour de la macro __STDCPP_DEFAULT_NEW_ALIGNMENT__. Clark Nelson ne se souvient pas d'avoir entendu une réaction en ce sens.
Mike Miller pose la question de l'appel explicite aux nouveaux opérateurs new sur une plateforme où ils ne sont pas supportés. Clark Nelson explique les limites physiques qui peuvent découler des limites de l'éditeur de liens, par exemple dans ce cas de l'allocation de la pile ou dans le cas où un alignement de 1 Mo serait demandé.
Richard Smith demande si une implémentation peut donner ses limites d'alignement. Clark Nelson n'est pas certain, mais estime que ces limites, quelles qu'elles soient, ne doivent pas être les mêmes que std::max_align_t. Cela dit, la terminologie est correcte.
Mike Miller demande si une implémentation qui ne supporte pas l'appel implicite de la version de new avec alignement étendu permettrait malgré tout un appel explicite de cet opérateur. Clark Nelson est surpris par la question mais admet qu'elle est raisonnable. Mike Miller établit que l'on ne peut alors pas parler d'un mécanisme implementation-defined. Jason Merrill déclare que la plupart des implémentations vont vouloir le supporter de toute manière. Richard Smith est d'avis que l'écriture actuelle laisse entendre que documenter le pire cas d'alignement supporté soit essentiellement une obligation.
Michael Herrick demande si un Feature-Test Macro sera livré. Clark Nelson n'est pas convaincu puisqu'on ajoute déjà une macro. John Spicer préférerait que ces macros soient homogènes en termes de format.
Richard Smith parle du cas d'un Placement New variadique. On s'entend par contre sur le fait qu'on est dans les cas limites.
Dinka Ranns se questionne sur la différence entre la formulation actuelle, « An extended alignment is represented by an alignment greater than alignof(std::max_align_t) » et « An extended alignment is an alignment greater than alignof(std::max_align_t) ». Clark Nelson dit que c'est du texte préexistant. Richard Smith le fera sur une base éditoriale.
Clark Nelson questionne Richard Smith sur l'ordre des paramètres. Richard Smith dit qu'il y réfléchit. Mike Miller demande ce que LWG pense des changements. Clark Nelson dit qu'ils ont suggéré les changements mais ne les ont pas vus.
On apportera le tout en plénière vendredi.
Alisdair Meredith est parmi nous pour discuter de cette proposition. Malheureusement, la proposition dépend d'un issue (Core Issue 1343: Sequencing of non-class initialization) sur les expressions constitutives, mais Alisdair Meredith pense qu'on peut discuter de sa proposition malgré tout.
Les deux plus gros impacts de cette proposition seront :
Richard Smith fait remarquer que §15.4 p. 3 ne semble pas suffire pour une implémentation, mais qu'on pourrait s'inspirer de §15.4 p. 2 pour le réécrire.
On nettoie la terminologie pour couvrir les appelables en général, pas seulement les fonctions. Certaines retouches sont requises aussi : par exemple, la version nothrow d'operator new[] pouvait autrefois lever bad_array_length, une incohérence résolue depuis. Diverses retouches de modernisation terminologique sont faites au passage, car le texte de cette section recoupe des raffinements faits par CWG au cours de la dernière année.
J'ai perdu un bon bout des échanges à partir de 17 h, car JF Bastien est venu me chercher pour discuter de paramètres au démarrage d'un thread avec SG1; ce qui s'est passé entre 17 h et 17 h 30 à CWG m'a échappé.
Arrivé à brûle-pourpoint dans SSG1 alors que Vicente J. Botet Escribá expliquait son approche, j'ai pu donner un peu de contexte quant aux travaux préalables sur le sujet, à mon exposé lors de CppCon 2015 et aux échanges qui ont suivi, sur place et par écrit. Plusieurs remarques intéressantes ont été faites, et SG1 n'a pas atteint de consensus, bien que l'idée d'attributs un peu opaques de Vicente J. Botet Escribá semble avoir reçu un assentiment de principe de la majorité des gens sur place. Trucs à retenir, de mémoire (!) :
J'ai quand même passé une trentaine de minutes sur place. Merci à JF Bastien d'avoir pensé à m'avertir!
J'ai fait un bref retour dans CWG quelques minutes, juste avant la fin des travaux. Une discussion brève avec Roger Orr m'a permis de voir les grandes lignes de ce qui s'est passé en mon absence. J'ai fait une découverte cet après-midi sur la base d'un exemple, c'est-à-dire que ceci est légal :
struct B {
virtual void f() noexcept;
virtual void g();
virtual void h() noexcept;
};
struct D: B {
void f(); // ill-formed
void g() noexcept; // OK
void h() = delete; // OK <----------ICI
};
Ça m'a bien amusé. On a fermé les livres vers 17 h 35.
De retour à ma chambre. Za et Cindy m'ont amené manger un hamburger, ma foi délicieux! Il y avait un choix intéressant (incluant un burger végétarien pour Cindy), de bonnes frites mayo, de bonnes bières. Une mouette enthousiaste est venue à quelques reprises se poser sur notre table (oui, nous étions sur la terrasse et l'oiseau a eu le cran de venir sur notre table) piquer des frites à Cindy, qui n'avait heureusement plus très faim. Il faisait frais, mais quand le soleil plombait c'était suffisamment chaud pour que la plage soit une option (il y a une plage à quelques minutes de marche à peine de l'hôtel), alors nous sommes allés mettre les pieds dans le sable et dans l'eau (quand même froide) par la suite. Ça fait du bien de passer du temps avec ma belle Za après une grosse journée comme ça, même quand c'est court.
Retour à l'hôtel, un peu de travail. Za s'est couchée (les filles font de grosses journées de plein-air), Cindy est allée au sauna. Pour ma part, j'ai travaillé un peu, puis à 20 h je suis allé participer à une séance de résolution d'« issues » avec LWG.
Nous sommes environ une dizaine au début, une quinzaine en période de pointe. Une autre session de soirée, portant sur la réflexivité, a lieu dans la salle d'à côté. La réflexivité est un objet d'étude extrêmement important pour le proche futur, mais les issues de LWG sont pressantes pour C++ 17.
Je suis le scribe d'office cette fois encore. Soyez tolérant(e)s pour ce qui est du style...
Marshall Clow débute les travaux en indiquant que nous devrons traiter les problèmes de « priorité 1 » d'abord. Tout le reste est secondaire ce soir.
Idée : il semble y avoir une erreur de type Off-by-One dans la spécification de deux nouveaux algortihmes
Geoffrey Rohmer : peut-on avoir une idée sommaire du sens à donner aux algorithmes inclusive_scan() et exclusive_scan()? Thomas Köppe : c'est des sommes partielles dans le jargon du calcul à haute performance.
Walter E. Brown : ma compréhension du problème est que l'algorithme tel qu'originalement spécifié n'opérait pas sur les séquences à demi-ouvertes. Thomas Köppe et Patrice Roy expliquent brièvement ce que ces algorithmes font.
Walter E. Brown : j'ai vérifier les propositions originales et la terminologie a effectivement changé depuis. Neil Horlock : si nous corrigeons ce bogue, ne briserons-nous pas le code écrit depuis et qui dépend de cette spécification? Walter E. Brown : je ne pense pas. Marshall Clow : personne n'a encore implémenté le TS de parallélisme. Jonathan Wakely : personne n'a utilisé le TS pour faire des bêtises... du moins, pas encore.
Jonathan Wakely : j'ai confiance, maintenant que je comprends le problème, que le bogue rapporté est bel et bien légitime, et que le correctif est correct.
Thomas Köppe : la notation *j, ... est-elle correcte pour un intervalle vide? Jonathan Wakely : ce n'est pas une syntaxe valide pour C++, mais je ne pense pas que ce soit l'intention. Thomas Köppe : je sais, mais c'est présenté en notation tête, queue. Walter E. Brown : ce n'est pas tant une notation tête, queue qu'une séquence potentiellement vide.
Patrice Roy : cet algorithme ne retourne qu'un OutputIterator. Nous avons discuté d'un ajustement à un autre algorithme pour cette raison ce matin. Est-ce bien ce qu'on veut? Walter E. Brown : ceci me semble différent, du fait que l'on a un itérateur de fin pour la source ici. Casey Carter : non, on a le même problème car le concept modélisé est InputIterator. Marshall Clow : nous sommes hors-sujet (Patrice Roy : désolé!)
Jonathan Wakely : il y a une différence de fond entre la formulation initiale et la nouvelle, au sens du traitement de séquences sources vides (cas originalement impossible). Je pense que nous devrions traiter cet issue immédiatement, dû à l'urgence de la situation (une spécification incorrecte) et retoucher le reste ultérieurement.
Un vote favorable est tenu.
Alisdair Meredith : si nous avons plusieurs issues à traiter, pour lesquels nous avons une terminologie, nous devrions les traiter d'ici vendredi. Marshall Clow : il y en a cinq que je pense traiter avec vous ce soir.
Idée : dans les allocateurs polymorphiques, le type resource_type semble avoir été échappé par accident entre une proposition antérieure et la formulation soumise dans le Fundamentals TS.
Jonathan Wakely explique les problèmes encourus dû à l.'absence de ce type. Daniel Krügler : je pense que cela devrait être documenté. Alisdair Meredith : concrètement, le type est disponible, puisqu'il est dans le Fundamentals TS; il n'a simplement pas été promu à C++ 17. Jonathan Wakely : si je le prends du TS, les deux versions pourront ne pas concorder.
Marshall Clow : je ne retrouve pas de mention du type resource_adapter dans les minutes de cette rencontre. Jefffrey Yasskin : nous avions un chiffrier, et nous voulions que nos catégories soient exhaustives, mais je ne me souviens pas de ce cas-là.
Jonathan Wakely : l'idée ici est de ne pas encoder des types d'allocateurs distincts dans chaque type de conteneur.
Jonathan Wakely : en y pensant bien, je vois des voies de contournement. On peut laisser faire cet issue. Alisdair Meredith : je me souviens maintenant que l'on l'avait délibérément laissé tomber, n'étant pas convaincus que c'était essentiel.
NAD car ce n'est pas un mécanisme essentiel, et parce que l'on ne l'a pas échappé par accident.
Jonathan Wakely (à Nicolai Josuttis) : ici, nous avons un cas où une proposition de Nicolai Josuttis, qui dépend du fix (en apparence simple) de cet issue, pourrait ne pas être accepté pour C++ 17 si le fix en soi est refusé lors du vote. Pour cette raison, Jonathan Wakely recommande à Nicolai Josuttis de copier / coller le fix dans sa proposition pour qu'elle soit plus autonome.
Marshall Clow : si le fix passe, nous accepterons ta proposition et marqueront le fix « proposé » comme « résolu ».
Consensus sur le fix.
Idée : les implémentations peuvent cibler les types pour lesquels offsetof() est supporté, outre les primitifs.
Marshall Clow : dans les téléconférences, le choix de mot conditionally supported nous a été rapporté comme étant insuffisant pour le besoin des usagers. Jonathan Wakely : je suis d'accord. Il faudrait le supporter, ou non, et documenter notre choix. Techniquement (§1.4 p2.1) : « If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this Standard as “conditionally-supported” when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message ». Geoffrey Rohmer : du point de vue des usagers, pourtant, ça me semble convenable.
Jonathan Wakely : documenter l'absence de support, à tout le moins, serait utile. Marshall Clow : oui, en y pensant bien, c'est probablement la chose à faire.
Marshall Clow : dans libc++, nous ne faisons rien outre ce qui est exigé par le standard.
Walter E. Brown : je recommande que nous documentions notre opinion à l'effet que cette préoccupation ne nous semble pas fondée et que nous considérions ce dossier clos. Daniel Krügler : d'accord avec Walter E. Brown.
Un vote favorable est tenu.
Idée : les types servant a titre d'étiquette devraient-ils être default-constructible?
Jonathan Wakely : nous attendons une résolution de CWG 1518. Alisdair Meredith : quelque chose m'échappe dans ce débat. Jonathan Wakely : les types étiquettes devraient être utilisés par leur nom, pas implicitement.
Nous ne pouvons pas traiter ce cas ce soir.
Idée : un texte normatif fait une affirmation vague sur « most machines »...
Geoffrey Rohmer : je ne suis pas certain de la valeur de tout ça; j'ai envie de simplement rayer le paragraphe 61. Jonathan Wakely : je n'aime pas qu'un texte repose sur une note en bas de page numérotée, c'est difficile à entretenir. Alisdair Meredith : dans ce cas, seuls les entiers signés me semblent intéressants. Walter E. Brown : il est possible de référer à des notes en bas de page, c'est une bonne chose.
Jefffrey Yasskin : nous mettons à jour nos référence pour pointer vers C11. Est-ce que ces références-là sont mise à jour?
Marshall Clow : quelle est la résolution suggérée? Geoffrey Rohmer : rayer la référence à « most machines ». Patrice Roy : plus précisément?
Marshall Clow :
Walter E. Brown : de toute manière, ce passage n'est pas vraiment une note. C'est plus un exemple.
Marshall Clow : alors, ce sera de transformer "-??- [Note: is_modulo is false for signed integer types (3.9.1 [basic.fundamental]) unless an implementation, as an extension to this International Standard, defines signed integer overflow to wrap as specified by the reference mentioned in footnote 217. — end note]" en un exemple.
Il faudra réexaminer ce cas une fois le texte retouché.
Idée : une postcondition semble suspecte
Jonathan Wakely : je pensais que c'était un NAD, mais Eric Fiselier m'a convaincu de l'existence de cas pour lesquels la postcondition peut être rencontrée sans poser de geste, c'est-à-dire dans le cas de liens symboliques dangling. La résolution proposée me semble correcte.
Jefffrey Yasskin : la suppression doit-elle aussi viser la cible du lien symbolique? Geoffrey Rohmer : la note dans la résolution proposée est claire à ce sujet.
Un vote favorable est tenu.
Idée : restreindre le contrat du swap() non-membre
Marshall Clow : ceci devrait être couvert par la proposition d'Alisdair Meredith.
Alisdair Meredith : c'est sur ma liste de choses à faire cette semaine.
On ne peut rien faire pour le moment
Daniel Krüger a écrit les ajustements demandés. Walter E. Brown constate que les irritant sont disparus. Marshall Clow : appliquons-nous la résolution proposée?
Un vote favorable est tenu.
Idée : les règles contraignant les constructeurs de std::tuple sont trop souples.
(Patrice Roy : il y a eu des travaux préalables dans ce dossier, mais j'ai manqué une partie des discussions)
Alisdair Meredith : Howard Hinnant a reculé sur ce point il me semble, car la résolution proposée entraînait d'autres ennuis. Jefffrey Yasskin : ceci pourrait aussi entraîner des modifications à libc++; nous devrions en consulter les artisans.
Jonathan Wakely : le correctif proposé est de prendre la résolution, puis de se débarrasser de la partie « B » du issue 2549 qui devait ne servir qu'à titre indicatif. Alisdair Meredith : nous pouvons offrir à Howard Hinnant une chance de répliquer, mais je doute qu'il le fasse.
Marshall Clow : la résolution est donc d'adopter 2312 partie 1 et de se défaire de la partie « B » de 2549.
Un vote favorable est tenu.
Idée : les permissions de <filesystem> posent problème dans le cas des liens symboliques.
Daniel Krügler indique que Jonathan Wakely a préparé la terminologie. Il ajoute avoir reçu un commentaire de Billy O'Neal exprimant sa compréhension du comportement analogue avec Microsoft Windows. Marshall Clow indique que sur cette plateforme, on doit comprendre que le Caching de l'information des répertoires est susceptible de rapporter de l'information sur le lien symbolique, chose moins utile pour ce service. Jonathan Wakely n'est pas certain que cette information soit utile dans le cas sous étude. Marshall Clow loge à la même enseigne.
Walter E. Brown demande si Beman Dawes a jeté un oeil à ce problème. Marshall Clow pense qu'il était là lundi lorsque ce dossier a été débattu. Marshall Clow dit avoir une trace des remarques de Beman Dawes; il semblait estimer que la terminologie d'origine était incorrecte, mais que cela pourrait être corrigé après le CD.
Daniel Krügler demande à Jonathan Wakely ce qu'il en pense. Jonathan Wakely indique qu'il n'était pas au fait du dossier, donc qu'il fait présentement ce que le document prescrit, donc qu'il a le bogue. Jonathan Wakely fait remarquer au passage qu'à son avis, le texte sur les permissions se lirait mieux s'il était écrit en anglais plutôt qu'en opérations bit à bit.
Marshall Clow indique qu'Eric Fiselier implémente le tout de son côté et nous reviendra avec ses impressions, mais probablement pas ce soir.
Marshall Clow : considérons-nous ce cas réglé, sur la base de la résolution proposée, quitte à mettre les freins si l'expérience montre que nous avons fait une erreur?
Un vote favorable est tenu.
Idée : la gestion des erreurs dans filesystem::exists() est incohérente.
Marshall Clow : est-ce que la terminologie en ligne est à jour? Jonathan Wakely : il n'y avait pas de terminologie précédemment.
Jonathan Wakely : je pense que les deux versions de la fonction devraient être cohérentes.
Walter E. Brown : je me questionne sur la deuxième partie du protocole de résolution. Elle s'intitule Returns: mais porte sur une autre sorte d'effet, alors ne devrait-on pas lire Effects:?
Daniel Krügel propose une terminologie adéquate.
Un vote favorable est tenu.
Marshall Clow : on vise à être plus directs dans la formulation. Patrice Roy : ça me semble raisonnable. Walter E. Brown : tout me semble adéquat.
Un vote favorable est tenu.
Marshall Clow : je pense ajouter une session de soirée pour jeudi.
Patrice Roy : étant sur SG14, je ne pourrai pas y être.
Alisdair Meredith : à mon avis, la session de soirée de mercredi devrait être une rencontre de LWG en bonne et due forme. Il y a beaucoup à faire.
Fin de soirée. Il est tard, mais j'ai beaucoup à faire, alors travail, travail, scotch (quand même!), travail... et dodo vers 1 h.
Je prends mes courriels en me levant. Les messages qui circulent sur les listes de discussion sont parfois presque violents. On peut sentir la pression du vote de C++ 17 qui approche rapidement.
Ce matin, Za et Cindy dorment, et dorment, et dorment... Mais j'ai tellement de choses à faire que je ne m'en aperçois pratiquement pas. Vers 8 h 25, je descends travailler avec CWG. Pas eu le temps de déjeuner. La machine à espresso fonctionne mais ce qu'elle m'a fait est un peu clair à mon goût.
Nous allons commencer avec une proposition de J. Daniel Garcia.
L'idée de cette présentation est de permettre d'utiliser des annotations faisant partie d'un espace nommé en utlisant un using local à l'annotation, suivant une forme telle que [[using ns: att0, att1(arg), att2]].
Jens Maurer demande si dans une clause d'attributs, il peut y avoir une nidification récursive des espaces nommés. Ce n'est pas un problème pour le moment, mais... La notation utilisée ici empêche l'imbrication d'espaces nommés. J. Daniel Garcia dit qu'il demeure possible d'avoir recours aux attributs d'autres espaces nommés en explicitant leur appartenance.
Patrice Roy fait remarquer que cette nouvelle syntaxe se comporte différemment des using namespace ailleurs dans le langage :
#include <string>
[[using CC: att]] void f0(); // Ok
[[using CC: CC::att]] void f1(); // incorrect
void g() {
using namespace std;
string s0; // Ok
std::string s2; // Ok
}
Jens Maurer répond qu'il n'y a pas d'équivalent de l'espace nommé global ici. Jonathan Caves indique qu'entre [[ et ]], c'est un tout nouveau langage et une toute autre grammaire. Patrice Roy fait remarquer que cette variation grammaticale sera critiquée.
John Spicer fait remarquer que l'on a un mécanisme très ouvert qui permettra aux gens de se mettre dans le pétrin. Mike Miller se dit sympathique à cette remarque mais estime que c'est le problème des gens qui choisiront de se mettre dans le pétrin.
Fedor Sergeev souligne qu'on pourrait même glisser du code assembleur dans ces trucs-là. Jens Maurer confirme. John Spicer est inquiet de l'inclusion de jetons qui seraient des mots clés du langage. On parle d'ajouter une note non-normative à l'effet que les usagers des attributs choisiront le sens à donner à ces manoeuvres. Mike Miller suggère implementation-defined, John Spicer préfère « this rule imposes no constraints on how an attribute-using-prefix affects... ». J. Daniel Garcia rappelle qu'on peut avoir recours à des annotations de tiers partis, et qu'il faut que la note ajoutée à la proposition en tienne compte.
Jens Maurer fait remarquer que les codes des documents devraient être en minuscules.
On amènera ceci en plénière vendredi.
Jens Maurer dit que pour l'honneur, il faut trouver au moins une faute dans le document. On rit un peu.
Mike Miller dit que conditionally supported n'est pas ce qu'on vise ici. Il est préférable d'enlever conditionally. Hubert Tong explique que la nuance entre les deux termes est l'obligation ou non de générer des diagnostics. Mike Miller dit que dans ce cas bien précis, la terminologie utilisée devrait rejoindre celle des directives #pragma. Jason Merrill indique que le terme dans ce cas est implementation-defined, au sens de « ...has implementation-defined behavior ». Hubert Tong demande si l'intention est de forcer le compilateur à rapporter des diagnostics; on semble penser que oui, en particulier dans le cas des fautes d'orthographe (ce serait bête de ne pas avoir de diagnostic dans un tel cas).
John Spicer pense qu'on devrait imposer un diagnostic; utiliser un attribut dans un compilateur qui ne les supporte pas devrait faire échouer la compilation. Dans cette proposition, l'idée est différente. Mike Miller pense que c'est une question de QoI, mais cela entraîne une incapacité de diagnostiquer les fautes d'orthographe. On migrera donc de conditionally supported à implementation-defined. Ça demande de retoucher aussi le texte de D0028R4 (discuté plus haut).
J. Daniel Garcia va retravailler le tout et on se repenchera dessus tantôt.
Mike Spertus est ici, nous allons examiner son texte. Dinka Ranns sollicite Richard Smith et Faisal Vali par IRC.
Mike Spertus dit qu'il souhaite ajouter quelques exemples, mais souhaite vérifier s'il y a des irritants normatifs dans le texte actuel. Il dit avoir ajouté des remerciements pour Jens Maurer; Jens Maurer dit qu'ils se sont assis ensembles hier soir jusqu'à ce qu'il fasse presque noir. La terminologie a changé de manière significative depuis hier soir, mais le document vise C++ 17, ce qui lui cause un malaise (Mike Spertus confirme).
Mike Spertus explique l'idée derrière la proposition, soit alléger l'écriture du code en déduisant les types des paramètres d'un template sur la base d'un appel de constructeur, sans avoir à expliciter les types s'ils ne sont pas ambigus. Ceci peut réduire le besoin d'écrire des fonctions de fabrication :
void f() {
auto p0 = pair<int,float>{ 3, 3.14159f }; // Ok aujourd'hui
auto p1 = make_pair(3, 3.14159f); // Ok aujourd'hui
auto p2 = pair{ 3, 3.14159f }; // incorrect aujourd'hui, Ok avec cette proposition
}
Jonathan Caves demande quel est l'intérêt de cet ajout. Mike Spertus explique ce qu'il vise à faire. John Spicer demande si on doit passer par le template primaire. Mike Spertus dit que oui.
Hubert Tong est préoccupé par un possible accroissement des erreurs bêtes; il craint que la terminologie ne permette d'appeler les destructeurs accidentellement. Jens Maurer dit qu'il manque une phrase à §7.1.6.5 indiquant qu'un placeholder pour un class-type ne peut apparaître nulle part ailleurs.
Richard Smith aimerait que nous ayons une production grammaticale distincte pour ce mécanisme de déduction de types, qui empêcherait que la déduction ne soit résolue accidentellement comme nom de type, ça le rendrait plus confortable. Jens Maurer le pointe vers la grammaire où on voit simple-template-id, ce qui peut entraîner une ambiguïté grammaticale. Jens Maurer dit qu'ils ont travaillé fort pour bien expliciter leur vision pour les class templates mais n'ont pas trouvé les mots dans le standard existant pour bien appuyer leur démarche. Mike Miller demande si on doit ouvrir un issue en ce sens. Jens Maurer dit que oui. Ça fait deux issues si on compte l'ambiguïté grammaticale.
Richard Smith souligne son inconfort quant aux variations de comportement en fonction de la présence ou non de paramètres par défaut. Mike Spertus dit avoir choisi de ne pas supporter certains cas qui pourraient briser le code existant. Richard Smith rappelle que la première déclaration d'un template peut ne pas avoir de « valeurs » par défaut pour les paramètres, en particulier quand la déclaration apparaît dans plusieurs fichiers.
Richard Smith propose :
v<int> z(int);
v<int,int>; // ceci doit avoir du sens dans sa tête :)
extern v<int> z;
v<int> z(0);
Jens Maurer mentionne une préoccupation partagée avc John Spicer à l'effet que des exemples comme celui qui précède compilent différement selon le contexte. C'est vilain. Jason Merrill fait remarquer par contre que les cas qui mèneraient à ces situations un peu laides et sont sans doute des trucs qu'on ne souhaite pas encourager.
Richard Smith demande ce qu'on fait avec tuple<int>. Si on veut de la déduction, avec deux paramètres, que fait-on? On parle de trucs comme :
template <class ... Ts> struct tuple;
template <class ... Ts> void f(tuple<Ts...>);
// ...
void g() {
f(5, 5); // crée un tuple<int,int>? Doit-on utiliser make_tuple()?
tuple<int> t0(5,5);
tuple<string> t0("Yo"s,5);
}
Jason Merrill dit qu'il trouve préoccupant de voir une signature correcte, chercher à créer un objet, échouer et se dire « bon, ça cloche, alors je me suis peut-être trompé de type »? Jens Maurer pense que ça devrait peut-être retourner à EWG pour des conseils. Mike Spertus est d'accord en principe. Il dit avoir un peu peur de Scope Creep. John Spicer pense que les paramètres auto pour les templates ont leur place maintenant dans cette proposition.
Anton Polukhin est préoccupé par les unique_ptr et autres cas pour lesquelles il existe des spécialisations. Il voit poindre des risques d'ambiguité. Fedor Sergeev mentionne le cas des constructeurs hérités. Richard Smith voit des opportunités de déduire les constructeurs d'une classe parent de manière analytique...
Jason Merrill mentionne qu'on pourrait ne tirer les guides de déduction explicites que sur la base des constructeurs qui sont définis hors du corps de la classe, mais que c'est probablement une mauvaise idée. Mike Spertus dit que la déduction devra être stricte. Mike Spertus et Walter E. Brown comptent éplucher la bibliothèque standard pour détecter les impacts. On se demande si on peut aller de l'avant avec ça pour C++ 17 et faire les correctifs pour Issaquah.
Mike Miller dit qu'il faudra que ça revienne à EWG. On s'attend revoir la proposition en CWG par la suite.
Brève pause. N'ayant pas déjeuné, je m'endors un peu alors je me suis pris une portion de goûter un peu plus grande qu'à l'habitude : crèpes roulées en sandwich, bouchées végétariennes, fruits, café. Je bavarde un peu avec Hubert Tong, qui a une proposition fort intéressante sur la table en vue de samedi après-midi : il présente cette proposition comme une alternative à la surcharge d'operator.() mais je pense que sa proposition est intéressante dans une acception plus large encore, peu importe ce qui adviendra de la surcharge d'operator.().
Jens Maurer aide un peu J. Daniel Garcia à fignoler son texte. Richard Smith aide à Mike Spertus à régler les cas limites de sa proposition.
On revient aux travaux de J. Daniel Garcia.
On corrige des trucs de grammaire anglaise.
Richard Smith se demande si son implémentation doit rapporter ou non des problèmes. Il s'attendrait à ce qu'une proposition du genre lui dise quoi faire, mais il ne voit pas de recommandations claires quant au comportement de son compilateur. Jason Merrill dit que ça nous informe au moins du fait qu'on doit accepter un programme dans lequel on trouve des espaces nommés inconnus. Richard Smith demande quoi faire si on connaît l'espace nommé mais pas certains des attributs qui s'y trouvent, comme en compilant sur un vieux compilateur du code source produit pour un compilateur plus récent.
Jens Maurer demande de clarifier l'intention de l'effet de la proposition. J. Daniel Garcia dit que son souhait est qu'un compilateur ne rejette pas son code parce qu'il ne comprend pas une annotation. Jason Merrill demande si on parle d'un problème théorique ou d'un problème rencontré; J. Daniel Garcia dit qu'il y va de manière théorique. Mike Miller suggère de suivre la terminologie des #pragma. Évidemment, on ne peut pas forcer les vendeurs à faire quoi que ce soit, incluant suivre le standard, mais il faudrait expliciter l'effet d'un non-respect d'une clause.
On jongle avec l'idée de demander aux implémentations de fournir leur liste personnelle de jetons utilisables dans un contexte d'annotations. Jens Maurer s'en tiendrait au texte des #pragma, estimant ceci conforme à l'idée d'avoir une liste de noms. Jason Merrill suggère qu'on devrait passer à un autre point et accepter le texte sur la table. Richard Smith se dit d'accord si on ajoute le texte des #pragma.
On amènera ceci en plénière vendredi.
James Touton explique son idée de template avec paramètre auto.
Jens Maurer : dans §7.6.4 p5, l'écriture me semble récursive. Ce qu'on fait souvent est séparer en deux blocs, puis les nommer explicitement.
Richard Smith remercie James Touton d'avoir refactorisé des passages qui vieillissaient mal. John Spicer dit qu'une trace des changements aurait été utile.
Jens Maurer recommande d'harmoniser la notation entre placeholder-type et placeholder.. James Touton dit avoir pigé ces noms dans le TS des concepts. Richard Smith pense que placeholder-type est ce qui devrait être conservé.
Alors que nous discutons, Dinka Ranns entre dans la salle et nous indique qu'EWG souhaite une rencontre conjointe avec CWG à propos de la génération des opérateurs de comparaison, un des sujets chauds de la semaine.
Il se trouve que c'est une erreur de communication, mais que la rencontre porte plutôt que la déduction des types des templates, proposition de Mike Spertus discutée plus tôt avec CWG. Je relate tout ceci de mémoire car nous étions très nombreux dans la salle et que plusieurs d'entre nous étions debout, alors je n'ai pas pu prendre de notes sur le moment.
L'assemblée a invité Richard Smith à expliquer les irritants (surprises quant aux types déduits; problème des types par défaut qui peuvent varier selon les unités de traduction, ce genre de truc) et les extensions naturelles (déduction automatique de types variadiques, comme une fonction retournant un tuple<string,...> peu importe la signature qui sera choisie. Chandler Carruth nous a par contre mise en garde contre le risque bien réel de générer un monstre avec une quantité quadratique de types comme :
template <class T, ...>
tuple<(T,...)> f(); // appliquer ... à T ou quelque chose du genre, pas sûr de la syntaxe
template <class ... Ts>
auto g() -> decltype(f<Ts)>; // ouch!
Il n'a pas tort, c'est un prospect terrifiant.
Nous avons convenu d'options « saines » à court terme, pour être en mesure de voter quelque chose de pertinent à la fin de la semaine, mais sous une forme qui permettra de traiter la déduction implicite des nombres variadiques de types entre le moment du vote et l'officialisation du standard (à Issaquah) si les expérimentations d'ici là sont encourageantes, en les faisant passer comme des demandes d'ajustements mineurs soumises par des pays.
Les portes qui s'ouvrent devant nous incluront des trucs comme :
tuple<int,auto,auto,double> f();
... ce qui est en soit novateur et intéressant.
On prend un vote, extrêmement favorable, et il est midi
Je suis fatigué; je m'endormais avant de devoir me lever pour aller à la rencontre d'EWG. Je retourne à ma chambre faire une sieste express de 30 minutes, puis retour chez CWG...
...
... une trentaine de minutes, ça n'a pas fait de tort, mais c'est peu dans les circonstances. De retour au boulot.
James Touton reprend le pavé. Mike Miller est dans une forme endiablée aujourd'hui, lui qui est plutôt stoïque normalement. James Touton a fait des changements à son texte (des mises en relief pour faciliter le suivi) depuis ce matin, ce qui est très gentil de sa part.
Jens Maurer : §7.4.6.1 p2, je vois deux cas. Par contre, §5.3.4 p2, il y a le cas de new. Est-ce une omission?
James Touton : je l'ai échappé.
Jason Merrill : on peut simplement référer à §5.3.4 p2 pour le cas de new. C'est déjà couvert.
Jens Maurer : Ok.
On fait diverses corrections mineures (corriger un exemple, clarifier un passage, ce genre de truc). Jason Merrill mentionne l'éventuel cas d'un concept placeholder. Il n'est pas immédiatement évident qu'un concept pourrait servir à titre de non-type placeholder. Patrice Roy fait valoir que le concept pourrait servir de non-type placeholder pour une constante booléenne.
Daniil Tarakanov fait remarquer que dans §14.5.5.1, le contexte peut fortement influencer les déductions. Il se demande si une clarification est requise. Hubert Tong pense que le problème qu'il a en tête vient d'un autre bogue de formulation, et que ce passage est correct. On convient qu'une note explicative suffirait. On discute un peu des règles de spécialisations partielles, qui peuvent être affectées (ou non) par ce nouveau mécanisme. John Spicer fait remarquer que la formulation restreignant certains mécanismes à des contextes non-déduits mérite d'être retouchée pour éviter de laisser entendre que ces mécanismes ne peuvent être utilisés ailleurs.
Effets intéressants de cette proposition :
template <auto V> struct C {};
template <class R, class... Args, R (* f)(Args...)>
struct C<f> {}; // OK
template <class T, T i>
void f(int (&a)[i]);
int v[10];
f(v); // OK: T is std::size_t
Jens Maurer fait remarquer qu'il faudra documenter certains de ces nouveaux aspects dans l'annexe C.
On débat un peu du auto dans la déclaration d'un paramètre non-type. Jason Merrill pense que le type n'est pas type-dependent mais que le nom l'est. Si on fait decltype(V) pour un paramètre non-type auto V, on aura un type, mais ce ne sera pas auto. Richard Smith fait remarquer qu'à l'interne, on a techniquement des auto type-dependent et des auto qui ne le sont pas, et explique comment arriver à chacun. On pouffe de rire à la complexité absurde de la chose.
Cette section du standard sera très particulière à lire, dû au niveau absolument stupéfiant d'abstraction atteint. Ça en devient drôle, pour être honnête. Ce mécanisme sera utile et utilisable par des mortels, je pense bien, mais sa conceptualisation est spectaculaire. Le côté type-dependent ou non est difficile à déterminer à cause de trucs comme :
template <class T> struct X {
template <auto V = sizeof(T)> struct Y {}; // ici, ce que représente auto est type-dependent
};
template <auto V> struct Z {}; // ici, auto n'est pas type-dependent
Jens Maurer est sorti quelques minutes; j'ai géré le Wiki de mon mieux, alors j'ai des trucs succincts pour un bout.
Hubert Tong : nous voulons éviter la synthèse avec le type auto. Nous voulons une terminologie qui explicite la possibilité avec auto d'avoir un type plus spécialisé qu'un autre, comme auto* serait plus spécialisé que auto.
James Touton : pouvons-nous simplifier l'écriture en ajoutant un autre type T?
Daniil Tarakanov : nous ne voulons pas divers niveaux de spécialisation avec des nested placeholder types.
Hubert Tong : certains en veulent!
John Spicer : avec auto et auto*, ça devrait fonctionner dans un sens mais pas dans l'autre.
Jason Merrill : tu pourrais piger de la terminologie dans le Concepts TS. James Touton : oui, dans la section sur les λ génériques.
Mike Miller : en as-tu assez pour avancer? James Touton : oui, j'ai des retouches à faire. Hubert Tong : faudrait se revoir en personne. James Touton : je reviendrai demain.
Mike Spertus : j'ai mis à votre disposition une version à jour de mon document, sur la base de la rétroaction reçue. Mike Spertus demande quelques précisions sur le recours à auto.
John Spicer : pour les deduction guides, tu veux avoir le mot clé template n'est-ce pas?
Richard Smith : dans la nouvelle section, il est tentant de supprimer le volet template complètement, et d'ajuster deduction-guide à la liste de ce qui peut se produire dans §14 p1
John Spicer : il faut que les restrictions soient uniformes.
Richard Smith : dans §14 p1, il y a une liste de puces qui devrait être ajoutée à declaration-guide. Il y a aussi la question, distincte, des contraintes sur les paramètres. Mike Spertus suggère une approche qui, selon Richard Smith, évitera les violations d'ODR.
Mike Spertus : où dois-je inscrire les contraintes? Richard Smith : §14.9, et spécifie le sens à donner à ces restrictions. Il faudra aussi les ajouter à §3.1 p2. Thomas Köppe indique que les usagers peuvent définir ces guides localement pour se faire des raccourcis.
Jonathan Caves : ces templates doivent-ils être uniques dans leur portée? Richard Smith : je ne pense pas qu'ils définissent une entité nommée. Fedor Sergeev : je pense qu'on devrait les traiter comme des spécialisations partielles. Richard Smith : les deduction guides ne seront pas trouvés par name lookup. Mike Spertus : je pense que c'est implicite. Hubert Tong : ça devrait être dit.
Mike Spertus : je vois, j'ai écrit comment les trouver mais pas comment ne pas les trouver!
John Spicer : je ne vois pas pourquoi on devrait permettre ça. Richard Smith : je ne pense pas que les gens devraient écrire des deduction guides pour les templates des autres. Mike Spertus : la grammaire leur permet d'apparaître comme des membres de classe ou d'instance.
Hubert Tong : il faudra mettre à jour [basic.def] p1. Cette proposition a un effet mais n'introduit pas de nom.
Richard Smith : ma compréhension est à l'effet que ce nouveau mécanisme ne supporte pas encore les alias templates. Faisal Vali : il me semble naturel de le vouloir, mais c'est pas tout à fait là.
Richard Smith : §7.1.6.2 p2 the wording makes one wonder what the status of this feature is. There are clarifications required here
John Spicer : 13§.3.1.8 also needs clarifications. Where does the deduction guide go?
Mike Spertus : in the same scope as the corresponding class
Faisal Vali : since it's like a specialization, here's how I'd do it... (explains)
John Spicer : I understand, but that's not what the wording says
Richard Smith : you're saying we want member specialization of deduction guides... We don't want to go there this week >laughs<
John Spicer : the deduction guide more-or-less works like function templates
Jens Maurer revient. Je lui redonne le volant du Wiki.
Mike Spencer présente ses dernières retouches. On propose des retouches linguistiques pour clarifier le propos.
On a un cas particulier qui demande de la prudence, soit un union dont la représentation inclut des bits de padding qui peut ne pas être considéré comme un contiguous layout du fait qu'ils n'apparaissent pas aux mêmes endroits.
Richard Smith s'interroge sur la force de la clause indiquant que dans un union, tous les membres doivent avoir la même taille et être tels que tous leurs bits participent à leur représentation. Son questionnement est à l'effet de savoir si la définition est suffisamment récursive. Jens Maurer pense qu'on devrait assurer la récurrence aussi pour les class types, donc en faire une puce différente de celle des scalaires. Jens Maurer demande si, pour un class type, le padding pose problème. Hubert Tong dit que cela est géré par une clause antérieure.
John Spicer demande comment les bitfields se comportent avec ce mécanisme. Tout le monde éclate de rire. Hubert Tong estime que la clause qui tient compte des bits de padding clôt le dossier, du moins en présence de padding bits. Jonathan Caves lance à la blague qu'on devrait demander au compilateur s'il insère du padding ou non. Richard Smith propose une écriture alternative.
On prend une pause vers 15 h 17. Richard Smith soulève en discussion privée avec Michael Spencer et Thomas Köppe la question des union sans membres actifs. Méchant, méchant... Je prends un petit gâteau aux fruits, un peu de café, quelques noix, et j'essaie de reprendre un peu du temps « perdu » car je suis en retard dans tout.
Les britanniques ici, et il y en a quelques-uns, regardent souvent ce qui se passe chez eux car le vote sur le Brexit (scission possible de l'Angleterre de l'Union européenne) se tient demain.
On recommence à 15 h 41. Des gens arrivent avec de jolis shooters aux fruits qui n'étaient pas là quand je suis allé grignoter. Zut!
Jens Maurer explique les changements les plus récents.
Hubert Tong demande quand il doit y avoir un diagnostic. Jens Maurer explique que ça se limite aux cas où les deux opérandes sont du même type (on ne traite pas les cas parent/ enfant), dans une même unité de traduction.
Jens Maurer dit avoir terminé son rapport. Les remarques de CWG ont été acheminés à EWG et ont été traités.
On amène ceci en plénière vendredi.
Gabriel Dos Reis présente la situation.
Hubert Tong : il y a des opérateurs pour lesquels l'ordonnancement est moins strict que l'ordonnancement par défaut, par exemple les opérateurs surchargés. Gabriel Dos Reis demande un exemple. Jason Merrill parle de l'opérateur +, et des opérateurs surchargés en général. Hubert Tong : pour chaque cas dans la clause 5, on a cette situation, alors vous voudrez une solution générale. Jens Maurer demande pourquoi. Hubert Tong demande s'il est volontaire que l'ordonnancement faible demeure même pour les opérateurs surchargés. Gabriel Dos Reis dit oui, donc que les garanties d'ordonnancement différeront dans les cas suivants :
operator+(a,b); // ordonnancement fort des appels de fonctions (était indéterminé, sera déterminé)
a.operator+(b); // ordonnancement fort des appels de fonctions (idem)
a + b; // ordonnancement faible des opérateurs (non séquencé avant, demeure ainsi maintenant)
John Spicer dit que dans §6.4, on trouve un embryon de formulation qui pourrait être enrichi pour clarifier l'intention ici. Jason Merrill pense que l'état actuel de la situation est non-normatif, étant décrit dans une note.
Le standard semble s'auto-contredire dans certains cas, et tenir une position non-normative.
James Touton vient demander à un membre de CWG d'aller expliquer à EWG un cas de bris de code sur la base de sa proposition. John Spicer y va pour nous.
Jens Maurer fait remarquer que f()+g() demeure non-séquencé selon cette nouvelle approche. Ça semble être le cas. Jens Maurer demande que §1.9 p16 soit précisé dans le texte du standard car il entre maintenant en contradiction avec la proposition discutée.
Maxim Kartashev pense que §5.2.2 p4 échappe aux paramètres par défaut dans sa formulation actuelle, ce qui peut jouer des tours si le souhait est de garantir un ordonnancement.
Fedor Sergeev indique que §5.2.2 p8, qui parle de l'ordonnancement des expressions préfixes et postfixes, devra aussi être ajusté.
Roger Orr fait remarquer que ce qui est présenté à la section 8 pourrait être retiré, pour qu'il soit clair que cela fut rejeté.
Pour le reste, on fait surtout des retouches de forme et de conformité aux usages du standard.
Jens Maurer suggère qu'on examine la version retouchée avant de trancher.
Jens Maurer parle de §3.1 p8. Ceci met-il suffisamment en relief l'impact de l'héritage? On s'entend pour « with at least one dot-access function ».
Gabriel Dos Reis : quand on a un objet avec operator.() et quand on l'utilise pour initialiser une référence, quelle sera la mécanique? Jason Merrill pense que §5.1.2 touche aux conversions vers des types références, entre autres. Il y a un lien à faire. Gabriel Dos Reis : utiliser une référence intelligente sur un int pour initialiser un int& est Ok, mais qu'en est-il d'utiliser cette référence intelligente pour initialiser un double? Faudrait clarifier à §5.1.
Jens Maurer : dans §8.5.3 p5, on a une référence (!) vers une autre section qui semble suspecte.
(Richard Smith doit quitter pour aller présenter un truc dans un autre groupe; Ville Voutilainen vient prendre Bjarne Stroustrup mais on ne peut pas l'avoir à deux endroits en même temps, pour deux trucs essentiels; trop de choses lourdes en même temps!)
Barry Revzin demande une précision sur §13.3.1.8, sur le nombre de cas couverts, mais semble satisfait de la réponse. Jens Maurer fait remarquer que le concept de séquence dans §13.2.1.8 est problématique.
Richard Smith dit que la nouvelle écriture semble laisser ouverte la possiblilité de surcharger operator.() sur la base des spécifications d'exceptions. Il indique aussi qu'il faut mettre à jour la définition de signature pour tenir compte du type de retour.
Jens Maurer parle de §9.3 p10, en partie redondant avec §13.5.6; il estime que c'est dans cette dernière que les définitions en question devraient converger. Il se dit aussi incertain de ce qu'apporte vraiment §9.3 p10. Gabriel Dos Reis trouve que c'est une bonne idée, faudra simplement formuler le tout.
Jens Maurer demande ce qu'est un cv-qualified reference type. C'est un terme inhabituel dans le standard. Bjarne Stroustrup explique qu'à l'origine, il n'y avait pas de restriction sur le type de retour, mais l'idée est de permettre d'enchaîner implicitement les « . » comme on le fait avec « -> » depuis longtemps; si on retourne quelque chose qui n'a pas l'opérateur « . », ça ne compilera pas de toute manière. Gabriel Dos Reis dit qu'on s'attend à autre chose que void. Jens Maurer explique que le texte dit autre chose. On confirme qu'on peut en fait retourner void, ou même this, comme dans le cas de operator->, mais c'est à nos risques et périls.
Jens Maurer : peut-on définir operator.() pour un union? Gabriel Dos Reis : oui.
Quelques suggestions sont faites pour clarifier le propos, bien sûr. Il y a une manoeuvre qui permet de contrôler le sens de l'opérateur d'affectation, par exemple :
struct A { int x; };
struct B { int x; int y; };
struct C {
A& operator.();
B& operator.();
};
void f(C& c) {
c.y = 42; // Ok
c.x = 7; // ambigu
}
struct D {
A& operator.();
};
D d1 { };
D d2 { };
d1= d2; // OK: invokes A::operator=; <---- ICI
struct E {
A& operator.();
E& operator=(const E&) = default;
};
E e1 { };
E e2 { };
e1 = e2; // E::operator=
John Spicer fait remarquer que pour trouver une fonction, la séquence proposée par le texte demande d'appeler operator.() avant de regarder dans les parents. C'est surprenant à ses yeux. Gabriel Dos Reis lui-même semble surpris :
struct X {};
class B { void f(); };
struct D : B {
X& operator.();
};
D d;
d.f(); // ne voit pas d.B::f()! Faudrait un using B::f dans D... Ce serait pire si X::f existait!
B &b = d; // que se passera-t-il?
Bjarne Stroustrup convient que c'est un cas qui leur a échappé. Cela dit, Roger Orr trouve une clause qui trouverait B::f() éventuellement, du moins si la formulation des cas permettait de s'y rendre (une séquence d'« otherwise » qui contourne le cas souhaité, sorte de « deux else pour un même if »). C'est donc récupérable. Il y a lieu de donner un rôle privilégié aux classes parents en relation avec operator.() et ce qu'il retourne.
Faisal Vali demande si une ambiguïté sur la base des services offerts par de multiples parents devrait mener à l'exploration des options par la voir d'operator.(), mais on convient que non. Ouf!
Jens Maurer soulève la question de la formulation precomposed-with et precomposed-by. Quelle est l'opération attendue? Richard Smith pense que l'intention est prefixed-with/ prefixed-by. Gabriel Dos Reis explique :
struct A { int x; };
struct B { A& operator.(); };
struct C { B& operator.(); };
C c{};
c.x; // atteint le x du A& éventuellement retourné
Jason Merrill dit ne pas être sûr qu'on ait besoin de définir tout ça. Gabriel Dos Reis pense qu'il faut expliquer l'intention formellement, entre autres pour définir l'ordre des évaluations. Jens Maurer pense qu'on cherche ici à lever des ambiguïtés. John Spicer soulève la question de l'enchaînement dans le cas où il y a plus d'une surcharge d'operator.() dans un même type : va-t-on au membre le moins profondément caché ou explore-t-on toutes les options dans chaque cas? Selon Gabriel Dos Reis, ceci est ambigü :
struct A { int x; };
struct B { A& operator.(); };
struct C { A& operator.(); };
struct D {
B& operator.();
C& operator.();
};
D d{};
d.x; // ambigü
Ceci est légal :
struct A { int x; };
struct B { int y; A& operator.(); };
struct C { A& operator.(); };
struct D {
B& operator.();
C& operator.();
};
D d{};
d.y; // Ok
Bjarne Stroustrup dit que si on explore le chemin de gauche, puis celui de droite, et qu'on trouve ce qu'on cherche dans les deux cas, faudrait que ce soit ambigü. Reste juste à l'écrire correctement. Jens Maurer dit que les règles en ce sens pour l'héritage multiple ont été réécrites dans le sang et la douleur il y a dix ans, et qu'il préférerait sincèrement ne pas recommencer. Gabriel Dos Reis est entièrement d'accord. Jens Maurer va donner un coup de pouce.
Mike Miller dit qu'il faut arrêter pour aujourd'hui. Gabriel Dos Reis et Bjarne Stroustrup pourront faire les retouches identifiées d'ici demain. En écoutant des remarques de Jens Maurer, j'ai compris la difficulté inhérente à la compréhension du code enrichi d'operator.(), c'est-à-dire que désormais, ce qui semblait être une valeur, avec accès direct, doit être considéré comme une potentielle indirection, avec toute la complexité inhérente aux appels polymorphiques. Pas simple...
De retour à ma chambre d'hôtel, Za et Cindy examinent une tablette électronique. Il se trouve qu'elles ont passé la journée à faire du géocaching, mais avec des indices en finnois, traduits par Google Translate pour ajouter de la difficulté. Elles ont beaucoup de plaisir! Moi, j'ai l'impression d'avoir passé une heure à changer le sens du verbe être... Mais je me suis aussi bien amusé!
Nous allons prendre une marche, manger un peu de sushi, acheter une bière pour la fin de la soirée, puis c'est le retour au boulot pour moi et le géocaching pour mes compagnes de voyage.
Encore ce soir, nous étions nombreux (la salle était presque pleine à mon arrivée) et Marshall Clow était en train de chercher un scribe pour la rencontre de LWG à laquelle je comptais participer. Étant habitué, j'ai accepté de le faire, ce qui explique que ce qui suit soit plus succinct que quand je prends des notes pour moi-même.
Marshall Clow : il y avait un support modéré pour cette proposition à LEWG
Geoffrey Rohmer : l'intérêt de la proposition est qu'elle est générique en fonction du type de pointeur, incluant ceux de boost.
Walter E. Brown : a-t-on livré le Library Fundamentals TS v2? Geoffrey Rohmer : le vote a eu lieu, mais il me semble qu'il reste une étape au processus. Hans Boehm : il n'y a plus qu'un seul vote par TS, pour accélérer la procédure. Walter E. Brown : je crains que l'on n'ait pas de véhicule pour cette proposition alors. Marshall Clow : on peut au moins voter pour le volet weak_ptr_type. Walter E. Brown : je propose qu'on vote immédiatement sur ce volet alors.
Beman Dawes : a-t-on l'opinion de Peter Dimov sur ce sujet? Patrice Roy : il n'était pas dans la pièce quand nous en avons discuté à Kona.
Patrice Roy : le type weak_ptr_type n'est qu'un petit outil servant à alléger l'écriture du code source. C'est inoffensif.
Marshall Clow : souhaite-t-on l'intégrer à C++ 17?
Le vote fut favorable.
Alisdair Meredith : j'ai amené cette proposition à LEWG avec une partie « forte » et une partie « faible »; LEWG a accepté à peu près la moitié de ma partie « forte » et la moitié de ma partie « faible »... La terminologie est, pour l'essentiel, « cut this part, move this to annex D ».
L'annexe D est l'endroit dans le standard où sont déplacés les éléments dépréciés
Marshall Clow : je veux qu'il soit clair que l'on parle de déprécier des éléments, pas de les supprimer. Il se cache des trucs dans l'annexe D qui y sont depuis C++ 98.
Patrice Roy : vous savez que quelqu'un dans SG14 travaille activement sur un raffinement de raw_storage_iterator ces jours-ci? Alisdair Meredith : euh, ce type est brisé, et je ne propose que de l'envoyer à l'annexe D. Tony Van Eerd : en fait, c'est plus facile de réparer quelque chose si ça a été déprécié au préalable. Nous pouvons dire « Nous avons brisé votre code? Voyons, nous vous avions dit de ne pas toucher à ça! ».
Marshall Clow : libc++ se sert de get_temporary_buffer() à l'interne pour quelques algorithmes. Je ne suis pas confortable de m'en défaire.
Alisdair Meredith : alors il faudrait le réparer avec un mécanisme RAII car c'est foncièrement dangereux présentement.
Walter E. Brown : sommes-nous disposés à retenir cette proposition jusqu'à ce que cette question soit résolue? Alisdair Meredith : je peux enlever cette fonction du lot, mais je préférerais garder la proposition entière.
Hans Boehm : cette fonction devait-elle se comporter comme une sorte d'alloca()? Marshall Clow : oui, si je comprends bien. Alisdair Meredith : c'est supposé être plus efficace que malloc(), sinon c'est cette dernière qu'on utiliserait. Anthony Polukhin dans libstdc++, on fait un truc spécial avec get_temporary_buffer(). Ça passe par des algorithmes suboptimaux quand l'algorithme de base échoue, et on est efficaces dans le cas contraire. La fonction peut allouer plus que ce dont elle a besoin et gérer cette mémoire par la suite.
Beman Dawes : le problème de cette fonction est son interface; mieux vaut la déprécier, et on la ramènera ultérieurement si quelqu'un fait une proposition l'améliorant.
Tony Van Eerd : cette fonction ne peut être une sorte d'alloca(), car son contexte de pile serait disparu suite à l'appel. Cela dit, la bibliothèque standard peut faire de la magie.
Anthony Polukhin : y a-t-il un impact sur clump()?
Alisdair Meredith : dans le cas de std::allocator, nous enlevons la spécialisation pour void et tout ce qui peut être déduit sur la base de traits. Tony Van Eerd : depuis quand a-t-on allocator_traits? Alisdair Meredith : depuis C++ 11, mais std::allocator est là depuis 1998. Tony Van Eerd : à quoi servait allocator<void>? Alisdair Meredith : ça ne faisait rien, même pas de l'allocation, mais ce type était parfois généré pour des raisons mécaniques. On n'en a plus besoin car on peut synthétiser le code équivalent par allocator_traits. Detlef Vollman dit que retirer ce type serait un problème, mais pas le déprécier.
Daniel Krügler : la dépréciation prépare le terrain pour une éventuelle suppression.
Tony Van Eerd : si j'ai mes propres allocateurs, devrais-je les modifier? Alisdair Meredith : je ne pense pas.
Alisdair Meredith : j'éliminerais totalement raw_storage_iterator.
Alisdair Meredith : je déprécierais is_literal_type, qui n'a pas de sens et ne peut être utilisé en pratique. Ça permet seulement de savoir si un type possède un constructeur constexpr, sans savoir lequel. Tony Van Eerd : nous avons cela depuis...? Alisdair Meredith : C++ 11.
Marshall Clow : et pourquoi déprécier std::iterator? Alisdair Meredith : nous encourageons les gens à ne plus utiliser ceci désormais. Dietmar Kühl : c'est pourtant très utilisé. Neil Horlock : c'est une pratique que nous souhaitons activement décourager. Tony Van Eerd : pourtant, ça ne fait pas de mal. Marshall Clow : c'est une étrange manière d'écrire cinq typedefs.
Marshall Clow : le reste de la proposition est fait d'ajouts à l'annexe D des trucs retirés du standard par le reste de la proposition. Geoffrey Rohmer : la terminologie pour ce qui a trait à allocator<void> dans l'annexe D va demander quelques explications. Alisdair Meredith : d'accord.
Tony Van Eerd : pourquoi préservons-nous la formulation de ce que nous relogeons dans l'annexe D? Patrice Roy : heureusement que nous le faisons, quand bien même ce ne serait que pour documenter les raisons de leur dépréciation. Ça peut facilter la tâche de les récupérer ultérieurement.
Ville Voutilainen : je viens de remarquer que cette proposition déprécie std::iterator. Avez-vous une idée de la quantité de code que cela brisera? Alisdair Meredith : c'est une dépréciation, pas une suppression; ça ne brisera rien. Ville Voutilainen : avec certaines options de compilation, les avertissements sont considérés comme des erreurs. Alisdair Meredith : nous n'avons pas à insérer [[deprecated]] dans le code de la bibliothèque, en pratique. Tony Van Eerd : je ne considère pas ceci comme un bris de code, mais je pense qu'on devrait tenir compte du nombre de gens qui vont constater des avertissement de dépréciation.
Ville Voutilainen : pourquoi déprécier ce type? Beaucoup de programmes s'en servent et en profitent. Anthony Polukhin aucune implémentation raisonnable n'offrira d'avertissement de dépréciation sur std::iterator pour au moins dix ans, mais nous pouvons espérer que la documentation de cette dépréciation amènera les gens à mettre leur code à jour d'ici lors. Alisdair Meredith : c'est LEWG qui recommande cette dépréciation. Dans le moment, ce type pose problème dans le cas des dependent base classes
Nicolai Josuttis : je ne pense pas que nous devrions tenir cette conversation, ce n'est pas notre rôle.
Neil Horlock : cette dépréciation est un message envoyé aux usagers.
Beman Dawes : nous devons cesser de perdre du temps sur cette question. C'est une décision de LEWG, et notre responsabilité et d'examiner la terminologie.
Alisdair Meredith : il ya un problème terminologique avec allocator<void>.
Tony Van Eerd : j'aimerais que, dans un document de dépréciation, nous distinguions visuellement les choses neuves et le fruit des déplacements.
Marshall Clow : est-ce que la terminologie porte bien l'intention?
Le vote fut favorable.
Marshall Clow : j'ai entendu des préoccupations à propos de std::iterator et de get_temporary_buffer(). Avons-nous d'autres messages à envoyer à LEWG? (semble que non).
Walter E. Brown : ils pourraient procéder malgré nos doutes. Il y a des précédents.
Walter E. Brown : sépare-t-on le groupe en deux pour aller plus rapidement? Marshall Clow : il faudrait un animateur pour l'autre groupe. Alisdair Meredith : je pourrais mais j'ai des propositions sur la table. Beman Dawes : je peux le faire quand nous discuterons des documents de Alisdair Meredith.
Nicolai Josuttis : nous n'avons pas avec nous Stephan T. Lavavej, Jonathan Wakely et Howard Hinnant ce soir. Je préférerais que nous soyons extrêmement prudents.
Marshall Clow : progressons en grand groupe. Nous avons passé suffisamment de temps sur ce dossier.
Alisdair Meredith : ce que nous avions était trop complexe et trop flexible; beaucoup de ce qu'il y avait là-dedans était inutilisé en pratique. Ce que nous proposons est une série de formules indiquant « if you don't do this, we'll supply it for you » et « if you do provide it, here's the name / the signature to use ».
Geoffrey Rohmer : pourquoi const_void_pointer est-il encore dans allocator_traits plutôt que dans pointer_traits? Alisdair Meredith : c'est une erreur, merci! Beman Dawes : c'est répété au moins cinq fois.
Alisdair Meredith : Ok, je vais nettoyer cela et vous revenir un autre jour. Si on a trouvé plusieurs erreurs ausi rapidement, c'est que le document n'est pas prêt.
(J'ai dû aller parler avec Ville Voutilainen, et j'ai manqué le début des échanges)
Alisdair Meredith présente la situation. Marshall Clow : comment parviens-tu à faire ce qui est écrit dans ce document, concrètement? Alisdair Meredith : ... hum ... je mens. Cette phrase manque d'amour, je vais la retravailler.
Anthony Polukhin : il y a quelque chose de semblable dans la fonction swap() de std::string; cette méthode swap() eest noexcept. Il pourrait être sage de les synchroniser.
Patrice Roy : sommes-nous disposés à voter sur une terminologie qui repose sur des mensonges ou sur de la magie? Alisdair Meredith : le problème est surtout la manière dont c'est présenté. Geoffrey Rohmer : je ne suis pas certain que ce soit faux. Alisdair Meredith : peut-être. J'ai écrit ça il y a quelques mois.
Marshall Clow : que swap() soit noexcept est un bloc de base pour l'écriture de code exception-safe. Je suis très inconfortable à l'idée de perdre ceci. Alisdair Meredith : ce qui était noexcept auparavant l'est encore maintenant. Auparavant, dans le standard, swap() n'était pas marqué noexcept car il s'agit d'un narrow contract. Concrètement, std::swap() n'offrait ni la garantie nothrow, ni une garantie d'exécution en temps constant sur des types arbitraires. Marshall Clow : il y a beaucoup de code dans le monde qui repose sur l'idée que swap() soit noexcept, et c'est ce que nous disons à nos usagers de faire.
Tomasz Kamiński : on vient de déplacer un test statique pour en faire un test dynamique. Alisdair Meredith : quand les allocateurs sont polymorphiques, on ne sait pas tout à la compilation. Tomasz Kamiński : peut-on toujours offrir une garantie nothrow à la compilation dans ce cas? Alisdair Meredith : ajouter noexcept à des endroits où cette qualification n'apparaissait pas préalablement n'est pas un objectif de cette proposition.
Daniel Krügler : j'ai un commentaire général à formuler. J'aime l'analyse d'Alisdair Meredith sur l'effet de la permutation des comparateurs, et je sais que ces permutations peuvent lever une exception, mais il me semble que nous perdons de l'information en acceptant cette proposition. Alisdair Meredith : ce que je présente n'est qu'un synopsis. Je n'ai pas retiré de spécifications d'exceptions qui auraient été là auparavant.
Marshall Clow : nous avons dérivé de notre mandat au cours des dernières minutes. C'est de ma faute, je suis désolé.
Nicolai Josuttis : je sais que nous aimons des phrases avec des mots tels que « unless » ou « otherwise », mais ce texte comprend des phrases avec plusieurs niveau de négation. Il faudrait reformuler... Walter E. Brown : pourquoi? Dietmar Kühl : pour comprendre ce qu'elles signifient! Alisdair Meredith : je peux aider à réécrire des passages si vous le souhaitez.
Daniel Krügler : j'aime bien les clarifications apportées ici, et j'aime beaucoup le retrait de cas de comportement indéfini.
Anthony Polukhin : les spécifications noexcept pour les conteneurs pourraient être améliorées. C'est Ok pour string, moins bien pour d'autres conteneurs...
Alisdair Meredith : je voulais un changement très restreint, pour livrer ce qui avait été annoncé.
Alisdair Meredith : les adapteurs de conteneurs ne sont pas décrits par des tables, donc j'ai utilisé une formulation distincte ici.
Marshall Clow : la spécification noexcept de stack est incorrecte, étant écrite comme si une méthode swap() serait appelée par l'implémentation, ce qui n'est pas garanti. Daniel Krügler explique son approche pour ce qui est de swap. Tomasz Kamiński : le problème est d'écrire la clause noexcept correctement. Daniel Krügler : j'étais heureux de voir ces clauses, même si elles sont incorrectes (certaines méthodes swap() sont protected). Alisdair Meredith : je vais retirer cette partie pour y réfléchir.
Marshall Clow : avec le pseudocode que nous avons ici, si propagate_on_swap est faux mais POCMA (propagate_on_move_assignment) est vrai, un mouvement pourrait se produire.
Tomasz Kamiński : que signifie la remarque « propagation traits are sane »? Alisdair Meredith : « sane » devrait écrire « same ».
Jonathan Wakely : qu'est-ce que TYPE? Alisdair Meredith : le type de données à permuter.
Marshall Clow : je pense que nous devons adresser certains irritants avec cette proposition avant de procéder. J'ai entendu que swap() sur des sequence containers peut désormais prendre un temps linéaire et lever des exceptions... Alisdair Meredith : je vais aller travailler là-dessus.
Patrice Roy : pourquoi se donner la peine de mettre des spécifications d'exceptions dans la bibliotheque standard si on ne peut pas les écrire correctement, sans avoir accès à using et à ADL? Alisdair Meredith : Daniel Krügler a écrit une proposition à ce sujet. Jonathan Wakely : il l'a fait fonctionner avec un nouveau trait.
Marshall Clow : prenons deux votes. Pensons-nous que cette proposition est prête pour C++ 17 dans la mesure où une mise à jour tient compte des irritants terminologiques?
Le vote fut légèrement favorable, mais avec opposition.
Jonathan Wakely : je suis contre car je crains d'aller de l'avant avec quelque chose d'aussi risqué tard dans le processus. Marshall Clow : devrait-on retourner ceci à LEWG pour leur demander de reconsidérer? Jonathan Wakely : que souhaite-t-on qu'ils reconsidèrent? Marshall Clow : je crains que nous ne brisions des contrats, avec des opérations clés qui ne sont plus noexcept et d'autres dont la complexité a changé. Nicolai Josuttis : je préférerais que les implémenteurs de bibliothèques standards en discutent entre eux. Le retourner à LEWG me semble contre-productif.
Alisdair Meredith : quelles sont vraiment les préoccupations? Marshall Clow : je pense que les gens seront surpris quand ils verront que l'on ne fait pas ce qu'on leur enseigne à faire, et quand leur code ralentira. Herb Sutter : ceci a-t-il été discuté avec LEWG? Alisdair Meredith : il est tard, je ne fais pas confiance à ma mémoire. Herb Sutter : parfois, retourner une proposition pour vérifier un cas limite... Alisdair Meredith : ce qui préoccupe Marshall Clow est au coeur du propos : nous souhaitons transformer du comportement indéfini en comportement défini, mais ça explique quelques surprises.
Jonathan Wakely : j'aimerais essayer cette proposition sur une base expérimentale d'abord.
Tony Van Eerd : le vote en LEWG avait autant de « neutral » que de « for/strongly for ».
Marshall Clow : votons-nous pour retourner la proposition à LEWG?
Alisdair Meredith : considérant que les « against/strongly against » dans la salle sont les implémenteurs, je pense que ce serait sage.
Le vote fut favorable, sans opposition, mais avec plusieurs « neutres ».
Pablo Halpern : le changelog montre ce que j'ai fait : essentiellement, ajouter constexpr et un exemple. Cette proposition est comme apply() de C++ 17 mais pour construire des objets à partir de tuple, relayant les paramètres du tuple au constructeur de l'objet en question. C'est une fabrique.
Walter E. Brown : la demande pour ce mécanisme faiblit-elle avec l'adoption probable de la proposition de Mike Spertus dans C++ 17? Pablo Halpern : non. Les membres de LEWG ont examiné le tout, se sont demandé si d'autres mécanismes en réduiraient la pertinence, et ont choisi d'aller de l'avant.
Nicolai Josuttis : les gens qui suivent mes cours pour passer à C++ 11 demandent un tel mécanisme. Les gens veulent entreposer des données dans un tuple, puis les récupérer. C'est utile!
Jonathan Wakely : l'utilisation de pair dans cet exemple est non-conforming. Pablo Halpern : elle dépend du Copy Elision garanti, que nous aurons vraisemblablement avec C++ 17.
Tony Van Eerd : s'il y a lieu d'avoir apply(), il y a lieu d'avoir ceci.
Pablo Halpern : j'aimerais vous présenter la terminologie... (c'est essentiellement le code requis pour écrire cette fonction)
Anthony Polukhin : pourquoi avoir utilisé des parenthèses plutôt que des accolades? Patrice Roy : pour éviter de créer un initializer_list par accident. Dietmar Kühl : pouvons-nous passer un initializer_list? Patrice Roy : passe les valeurs entre accolades en tant que premier paramètre à la fonction.
Patrice Roy : nous devrions utiliser std::forward (utiliser explicitement std::).
Jonathan Wakely : devrait-elle être SFINAE-friendly? Tomasz Kamiński : apply() n'est pas SFINAE-friendly. Alisdair Meredith : j'aimerais faire ce travail de SFINAE-friendliness à plusieurs endroits pour ce qui est tuple-like, alors je préférerais passer un gros coup de balai d'un coup quand nous en aurons le temps.
Marshall Clow : envoyons-nous ceci dans C++ 17?
Le vote fut favorable.
Pablo Halpern : lisez à partir de la fin. Nous voulons changer un =default pour un =delete dans l'affectation des allocateurs polymorphiques. Ils apparaissent à peine alors on ne brise le code de personne.
Daniel Krügler : j'aimerais remercier Pablo Halpern d'avoir pris le temps d'écrire une motivation complète dans sa proposition.
Marshall Clow : a-t-on quelque chose à redire sur la
terminologie? (la proposition change un mot pour un autre... )
Marshall Clow : envoyons-nous ceci dans C++ 17?
Le vote fut favorable.
Tomasz Kamiński : avec cette proposition, je cherche à propager les catégories de valeurs (& et &&) d'un wrapper à la fonction qu'il enrobe (il explique ensuite le problème associé à la construction de not_fn en fonction du contexte de construction). Il présente deux terminologies et commence par la version qu'il dit « minimale ».
Nicolai Josuttis : pourquoi deux terminologies? Jonathan Wakely : LEWG n'aimait pas la version détaillée, et à demandé à Tomasz Kamiński de revenir avec une terminologie plus légère et de laisser LWG décider.
Nicolai Josuttis : les deux occurrences de ref sont formatées différemment. Raison? Tomasz Kamiński : elles devraient être identiques, c'est un accident.
Jonathan Wakely : vaut-il la peine de critiquer la terminologie? Marshall Clow : voyons s'il y a des problèmes à adressser. Jonathan Wakely : g est toujours un lvalue. Elle porte un nom. Alisdair Meredith : c'est la chose dans laquelle la valeur de retour est entreposée, pas la valeur elle-même. Jonathan Wakely : je sais ce que ça cherche à exprimer, mais le texte ne porte pas bien l'intention. Marshall Clow : a-t-on des critiques non-terminologiques avec ce texte? Jonathan Wakely : oui, beaucoup.
Marshall Clow : examinons l'autre terminologie. Tomasz Kamiński présente la version détaillée.
Alisdair Meredith : le constructeur à partir d'un F&& laisse croire que tu cherches à relayer plutôt qu'à déplacer. Tomasz Kamiński : non. Alisdair Meredith : mais tu utilises forward, pas move... (Jonathan Wakely indique le type de F; Alisdair Meredith dit qu'il comprend).
Alisdair Meredith : le declval(result_of...) à titre de type de retour est-il nécessaire? Jonathan Wakely : oui, « result_of does the INVOKE dance... ». Alisdair Meredith : je pense qu'on peut simplifier tout ça. Jonathan Wakely : c'est exposition only; on pourrait simplement utiliser INVOKE.
Jonathan Wakely : ce que je n'aimais / n'aime pas est que cette description n'aide pas les usagers à comprendre ce que fait not_fn. Marshall Clow : j'aime que ce soit précis. Jonathan Wakely : j'aime que ce soit exact.
Marshall Clow : quelle terminologie préfère-t-on? Alisdair Meredith : la détaillée dit la vérité. J'aime mieux être véridique qu'être simple. Walter E. Brown : c'est impénétrable. Anthony Polukhin : c'est trop long.
Jonathan Wakely : call_wrapper devrait être un template. Ça devrait être en italiques.
Anthony Polukhin : quel est le problème avec la version courte? C'est lisible après quelques essais, mais il est tard... Jonathan Wakely : il y a plusieurs problèmes avec celle-là.
Marshall Clow : j'aimerais un consensus sur la version que nous préférons.
Daniel Krügler : je comprends les réticences de Jonathan Wakely's, mais je préférerais corriger les irritants de la version courte. Jonathan Wakely : la première version n'ajoute pas le support de SFINAE que tu souhaites, n'est-ce pas? Tomasz Kamiński : non. Daniel Krügler : si la première version ne fait pas tout ce qu'on attend, la terminologie devrait l'indiquer. Tomasz Kamiński : dans la première version, il est difficile de bien gérer les qualifications cv de g. Daniel Krügler : on devrait dire quelque chose du type, puis quelque chose des quaifications cv de ce type.
Marshall Clow : je comprends que Jonathan Wakely et Daniel Krügler préfèrent la première. Et les autres?
Alisdair Meredith : je crains que réparer la première ne nous mène à un monstre comme la deuxième, seulement autrement. Daniel Krügler : il faudrait l'expliquer par un exemple. Tomasz Kamiński : faudra du Boilerplate Code. Jonathan Wakely : la proposition toute entière est du boilerplate. On en aurait besoin dans une vraie implémentation, pas dans une spécification... Alisdair Meredith : peut-on simplifier en y allant par exposition-only? Tomasz Kamiński : oui. Jonathan Wakely : je suis opposé à expliciter tous les détails pour avoir exactement le joujou que je veux.
Daniel Krügler : est-ce que Stephan T. Lavavej l'a vu? Tomasz Kamiński : oui.
Marshall Clow : quelle version veut-on?
Le vote fut majoritaire pour la version plus complète.
Marshall Clow : comment rendre les gens plus heureux de la terminologie? Tomasz Kamiński : que devrais-je retirer? Walter E. Brown : rien. Il n'y a pas d'erreur technique.
Marshall Clow : que devrait-on changer? Jonathan Wakely : je n'aime pas que ce soit un bloc de code. Il y a plusieurs erreurs d'ordre éditorial.
Jonathan Wakely : devrait-on ajouter un opérateur d'affectation? Tomasz Kamiński : il y a eu un vote et ce fut rejeté.
Anthony Polukhin : devrait-on relayer les paramètres?
Patrice Roy : puisque la proposition est correcte et offre un mécanisme utile, bien qu'elle soit plus détaillée que souhaité, peut-on simplement l'accepter sur cette base, quitte à la rendre plus harmonieuse en fonction des spécifications semblables par la suite? Marshall Clow : ce n'est pas nécessaire.
Jonathan Wakely : noexcept devrait être sur la fonction not_fn(), pas sur le constructeur de call_wrapper.
Alisdair Meredith : pour INVOKE, ça peut attendre. C'est une bonne idée mais on a beaucoup d'autres trucs à faire.
Daniel Krügler : je pense que le constructeur n'est pas supposé être accessible aux usager. J'aimerais qu'il soit plus opaque... Jonathan Wakely : ...il pourrait être privé, et les implémentations le feraient fonctionner. Pas besoin de leur dire comment.
Marshall Clow : quelqu'un accepterait-il de passer les changements en revue, pour éviter une autre rencontre? Daniel Krügler : oui.
Marshall Clow : envoyons-nous ceci dans C++ 17?
Le vote fut favorable.
Marshall Clow remercie tout le monde d'être resté jusqu'à... 23 h 40.
Pensée pour mes concitoyennes et concitoyens de Boisbriand qui, pour la Fête nationale, ont droit à un concert des Trois Accords ce soir. Si j'étais à la maison, mes enfants et moi serions parmi vous (en fait, mes enfants y sont probablement sans moi!)
Je me suis levé en retard ce matin (merci à Cindy, qui a averti Za, et à Za qui m'a réveillée). Douche à la course, brossage de dents, et course vers CWG.
J'ai de la lessive à faire. Le service de l'hôtel est prohibitif. J'ai essayé de négocier le fait de faire ma propre lessive avec l'hôtel et il n'y avait pas d'ouverture. Za m'offre de s'en occuper. Immenses mercis mon amour!
Arrivé à CWG, salle pleine. Les travaux sur le document portant sur la clarification de l'ordre d'évaluation des expressions sont en cours.
Vive Jens Maurer et le Wiki pour le début de la rencontre; une partie de ce qui suit leur est dû.
Jens Maurer et Thomas Köppe : §1.9 p13 « every value computation and side effect associated with ... »
Richard Smith : §1.9 p16 supprimer le changement
Roger Orr : §1.9 p14 reformuler?
Jens Maurer : non, certaines full-expressions ne sont pas des expressions.
Thomas Köppe : §1.9 p13 « side effect » au singulier, à deux endroits.
Jason Merrill : il faut tout de même supprimer la note de §1.9 p16.
Jens Maurer : §5.2.2 p8, il faut citer un passage du paragraphe supprimé pour fins d'identification.
Barry Frezin : il faudrait déplacer « of a parameter » devant « the initialization of a parameter, and the initialization itself ».
Richard Smith : §5.3.4 p20, supprimer « if storage has been allocated » qui n'est plus utile.
Richard Smith : les braced-init-list sont évalués de gauche à droite. Jens Maurer : voir §8.5.4 p9.
Bon, je reprends le clavier. La discussion en cours porte sur l'ordonnancement des opérations dans un new de forme nothrow.
Hubert Tong demande si gcc et MSVC ont une implémentation expérimentale; les deux confirment.
Richard Smith : si j'ai a + b, avec la version par défaut, l'ordre est indéfini. Avec une fonction, on évalue de gauche à droite. Plus loin, c'est moins clair.
Jasom Merrill : je pensais que les changements que nos faisions reposaient sur la syntaxe. Il me semble qu'on s'éloigne du plan.
Jens Maurer : il se peut qu'on n'ait pas compris l'idée à cause de toutes ces notes. L'évaluation des paramètres aux fonctions dans le texte actuel demeure non-séquencé. Notre compréhension était que l'ordre d'évaluation des fonctions dans une expression était unsequenced, mais on a trois notes distinctes, deux qui disent unsequenced et une qui dit indeterminately sequenced.
Gabriel Dos Reis : je suis confus.
Richard Smith : faudra reculer sur le changement à §5 p4.
Bjarne Stroustrup : ce qui est mêlant, est-ce l'ordre d'évaluation left-to-right ou indéterminé?
Thomas Köppe : cette proposition force un ordre strict left-to-right. Jens Maurer : il faudrait retirer la note qui entraîne de la confusion. Gabriel Dos Reis : je l'ai retirée.
Hubert Tong : je n'ai pas d'exemple en tête de la différence entre unsequenced et indeterminately sequenced with respect to one another.
Thomas Köppe : l'ordre d'initialisation des globales dans deux unités de traduction distinctes.
Plusieurs échanges s'ensuivent dû à des notes contradictoires. Il est difficile de comprendre l'intention du document dans certains cas.
Mike Miller : on amène ça en plénière vendredi.
Gabriel Dos Reis : j'ai travaillé avec Jens Maurer hier soir et nous avons clarifié les points qui menaient à confusion. Ainsi, dans ce qui suit :
struct B { int x; };
struct S : B {
A& operator.().
const A& operator.() const;
AA& operator.();
};
... operator.() est traité comme un appel de fonction opaque, ce qui signifie que les services des classes parentes seront privilégiés sur l'exploration des options ouvertes par operator.(). Nous avons toutefois constaté des cas où nous ne voulons pas utiliser operator.(), par exemple :
struct B { int x; };
struct S : B {
A& operator.().
const A& operator.() const;
AA& operator.();
int m = x; // ne considérera jamais operator.() ici
};
Jens Maurer : ceci explique l'injection d'un fanion booléen dans le texte pour clarifier les mécanismes de name lookup. C'est explicite, encombrant, mais c'est ce qu'on a trouvé de mieux. John Spicer fait remarquer que ce cas-ci, bien précisément, est déjà couvert par le texte dans §3.4.1 p8. Gabriel Dos Reis indique d.'autres exemples :
this->x; // ne considère pas operator.()
(*this).x; // considère operator.(), mais faudrait pas, alors on a retouché pour que ça ne le fasse pas
Brève pause. Je bavarde avec Hubert Tong qui me confirme que la proposition vient de donner un sens à des trucs comme f(g(),h()) quand g() et h() ont des effets de bord, ce qui me rend triste, mais on ne peut pas gagner tous les combats. Je bavarde aussi avec Faisal Vali, chic type, qui est heureux de cet état de fait pour les cas simples, ce que je comprends; je lui explique que ce ne sont pas les cas simples qui me préoccupent, et on rit un peu, mais de toute manière c'est un combat perdu, et la majorité a parlé.
Croissant au brie, bouchées de saumon, fruits, café. Je n'avais pas déjeuné, m'étant levé trop tard, alors ça fait du bien.
Mike Miller examine les options pour la clarification des cas où operator.() s'applique, pour voir si on peut se rendre au vote demain avec un document auquel on peut avoir confiance. Hubert Tong rappelle qu'on a quelque chose de nouveau sur la table, et qu'il faudra faire un examen détaillé dans chaque cas. Il irait avec l'approche utilisant un fanion, pour être le plus explicite possible. Bjarne Stroustrup dit qu'il ne dira pas à CWG comment travailler, mais que leur proposition est analogue à operator->() et qu'il ne pense pas qu'on explicite chaque accès à -> dans le standard; il espère que l'on n'aura pas à faire bien plus complexe avec operator.(). Mike Miller dit que la subtilité avec operator.() est qu'il peut être appelé dans des contextes surprenants. Gabriel Dos Reis dit qu'à son avis, il faudrait présumer que c'est le « . » traditionnel jusqu'à preuve du contraire. Richard Smith n'est pas sûr que ce soit clair.
John Spicer pose la question de for sur des intervalles : dans v.begin() et v.end(), de quel « . » parle-t-on? Mike Spertus dit qu'un usager souhaiterait certainement qu'on trouve operator.() s'il existe. Jens Maurer dit que le problème est que les « réécritures » faites par le compilateur apparaissent ailleurs, en particulier avec operator->(). Bjarne Stroustrup dit que ça dépend de la manière dont on exprime les règles de réécriture. Hubert Tong fait remarquer que pour for sur un intervalle, il faudrait une position d'EWG. Jens Maurer pense qu'on devrait examiner les occurrences une par une, puis décider ensuite si on veut une écriture générale ou des écritures au cas par cas. John Spicer aimerais avoir une liste des lieux où il n'y a pas de changements pour s'assurer de ne rien avoir oublié.
Jens Maurer dit que §8.5.3, qui décrit les règles de surcharge, est une sorte de bombe à retardement; à chaque fois qu'on touche à cela, il y a des ajustements à faire dans les meetings subséquents. Il souhaite examiner les impacts en détail. Gabriel Dos Reis pense que le changement qu'il propose arrive tôt dans la séquence de règles et devrait donner une claire relation de priorité. Jens Maurer utilise l'exemple suivant :
struct A {};
struct S {
A& operator.();
};
A & a = S{};
void f(A&);
void f(A);
// void f(S); // à réfléchir, mais pas nécessaire pour être dans le pétrin
f(S{});
Ici, il faut générer une séquence implicite de conversions, mais comment est-elle spécifiée? Mike Miller indique que l'on ne sait pas même si on doit appliquer operator.() ici, sur quelle règle ou quel principe se baser. Gabriel Dos Reis pense qu'on doit traiter operator.() comme un opérateur de conversion. John Spicer dit que dans un tel cas, avec le langage que nous avons, il n'y a pas de mécanique permettant de réaliser l'overload resolution qui nous mènera à une solution.
Bjarne Stroustrup souhaite y aller doucement : on a un S, on examine les règles de conversion, on trouve une conversion vers A&, on appelle f(A&).
Mike Miller suggère d'ajouter void f(S). À ce moment, si les conversions sont faites d'abord, on ne verra pas void f(S) ce qui sera... surprenant.
Gabriel Dos Reis montre un exemple de la proposition, mais on reste confus. Bjarne Stroustrup dit avoir modélisé operator.() sur operator->(), pas sur les opérateurs de conversion; à son avis, c'est là qu'il faut placer le modèle conceptuel. Richard Smith dit que les deux opérateurs n'ont pas le même comportement : l'opérateur -> mène à un comportement déterministe, mais (dans les mots de Mike Miller) si operator->() te donne deux choix (pointeur, t'as fini; class type, tu continues à appeler ->), il se trouve qu'avec operator.() t'as class type, class type, class type...
La situation est tendue.
Jens Maurer revient sur l'exemple :
struct A {};
struct S {
A& operator.();
};
A & a = S{};
void f(A&);
void f(A);
void f(S);
f(S{});
Jens Maurer demande quel f() sera appelé. Bjarne Stroustrup pense que ce sera f(A&). Ça impliquera que f(S) ne serait pas vu. John Spicer mentionne que ce serait même le cas si f() était un membre de S selon lui. Après vérification, c'est effectivement le cas. Il se trouve que auto fonctionne en termes de déduction de templates; un truc comme auto r=S{}; ne donnera donc pas un S. Ça va jusqu'ici :
struct A {};
struct S {
A& operator.();
};
void f(S);
f(S{}); // ne compile pas!
Roger Orr a pensé à celle-ci. On ne peut pas passer une référence intelligente à une fonction avec le texte actuel. Jens Maurer fait remarquer qu'on ne peut pas appeler une méthode d'instance f() d'une référence intelligente r, techniquement, sans passer par (&r)->f().
La tension se poursuit. On peine à se rejoindre car il y a deux modèles mentaux en confrontation.
Jason Merrill demande s'il serait sage de consulter EWG pour savoir si l'impossibilité de passer une référence intelligente en paramètre à une fonction est un choix délibéré. Bjarne Stroustrup dit qu'ils ont voté pour, mais peut-être sans comprendre ce que ça signifiait. On peut selon lui toujours passer un pointeur sur une référence intelligente.
Richard Smith demande comment on peut obtenir un pointeur sur une référence intelligente si on ne peut pas passer celle-ci à addressof()... Ouch! Hubert Tong fait remarquer que LEWG ne sera pas content de celle-là. Bjarne Stroustrup dit que celle-là lui a échappé; faut absolument trouver le moyen d'obtenir l'adresse d'une référence intelligente.
Jens Maurer se demande s'il vaut encore la peine d'examiner la proposition à ce stade, avant que les questions de fond ne soient réglées.
Bjarne Stroustrup dit qu'il y a un seul problème à son sens, soit trouver le moyen d'obtenir l'adresse d'une référence intelligente. Il ne comprend pas pourquoi les gens dans la salle discutent d'overload resolution. John Spicer dit qu'il faut écrire ce qui se passe dans ce cas pour que les appels à operator.() puissent être résolus. Mike Spertus suggère qu'on traite le cas d'un seul operator.() par classe immédiatement, le cas de multiples versions étant à ses yeux plus complexe. John Spicer n'est pas convaincu qu'il y ait une véritable plus grande complexité. Jason Merrill a l'impression que la sémantique sera plus claire si on règle le cas de plusieurs operator.() tout de suite.
Mike Miller relance la question : a-t-on une chance d'en arriver à quelque chose de prêt à voter demain après-midi? Thomas Köppe dit qu'on peut essayer. Jens Maurer en doute. Hubert Tong demande qu'on sollicite une position de la part d'EWG sur la question « can you pass a reference-surrogate-type to a function that takes a function-surrogate-type? ». Bjarne Stroustrup dit qu'il posera la question à EWG sous la forme « CWG est confus, l'êtes-vous aussi même si c'est clair dans le document? ». Jason Merrill demande où c'est écrit dans le document.
Gabriel Dos Reis dit qu'il préférerait ne retourner devant EWG que si un changement de design survient. Mike Miller dit qu'à son avis, le document et les intentions des auteurs semblent contradictoires. Jens Maurer indique la page 9 du document design . Hubert Tong aimerait que la question posée à EWG soit celle qui a été formulée par CWG. Jason Merrill dit ne pas voir dans le document de design ce que Bjarne Stroustrup dit y trouver. Jens Maurer demande à Bjarne Stroustrup s'il convient avec lui que l'exemple à la page 9 montre une contradiction. Bjarne Stroustrup dit en effet, c'est soit un problème de design, soit un bogue.
On arrête à midi. Ouf. Il y a des gens qui ne sont pas contents dans la salle.
C'était un matin très tendu. Bjarne Stroustrup et Gabriel Dos Reis se demandent s'ils sont capables de réparer les trous dans leur design pendant le dîner; le problème est qu'il n'est pas possible d'examiner leur proposition de terminologie et de valider la conformité avec leur intention sans connaître cette intention au préalable. Le corollaire du problème est que le vote est demain, donc s'ils ne résolvent pas très rapidement les problèmes de design, il ne sera pas possible de faire l'analyse de leur document assez rapidement pour l'amener en plénière, du moins pas si on fait un travail rigoureux. Je leur ai souhaité bonne chance avant d'aller travailler à ma chambre.
Daniel Krügler nous écrit un mot à propos de la position de CWG sur le constructeur par défaut, explicite ou non, des types étiquettes. J'amène la question devant Jens Maurer et Mike Miller, mais il ne semble pas possible de clore ce dossier dans l'immédiat.
On examine la nouvelle version de la terminologie. Hubert Tong dit qu'il reste une retouche à faire (une précondition : « an array of unknown bound of incomplete type »), puis LWG peut prendre le relais. John Spicer demande si la question du padding est close, mais Richard Smith pense que la terminologie proposée couvre correctement ce cas.
Mike Spencer demande si on a un meilleur nom à suggérer. On n'a pas d'idées.
Jens Maurer demande si la définition est récursive pour les agrégats. Mike Spencer dit oui. Jens Maurer demande ce qu'on fait quand une classe a des attributs d'instance privés, par exemple ceci :
class X { int n; };
Hubert Tong dit qu'il faut revenir à une terminologie antérieure, qui parlait de direct subobjects. Faut s'assurer que la définition de value soit correcte.
Ça retourne dans le camp de LWG, qui la portera sans doute au vote vendredi.
On fait des retouches de langue mineures ici et là.
Jason Merrill demande pourquoi c'est à cet endroit que l'on décrit potentially-throwing. Jens Maurer pense qu'il y a de bonnes raisons.
On fait le tour, ça se tient. Ça retourne dans le camp de LWG, et on décidera c'est LWG ou CWG qui la portera au vote vendredi.
Daniel Krügler nous est revenu à ce sujet, du fait que LWG est bloqué par http://open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#1518 dans ce dossier, et ça commence à leur compliquer l'existence car plusieurs propositions en dépendent.
Le fait que ceci compile :
struct tag { explicit tag() = default; };
void f(tag);
void f(int);
void g() {
f(tag{}); // Ok
f(3); // Ok
f({}); // ambigü, mais c'est ennuyeux (devrait appeler f(int{}))
}
... complique singulièrement la tâche de programmer correctement avec des types étiquettes. Jens Maurer s'offre d'ajuster la terminologie de manière à éviter cet irritant.
Richard Smith dit qu'il reste une nuance entre les cas d'agrégats et de non-agrégats. Les types étiquettes tendent à être des agrégats.
Hubert Tong ouvre la porte à des champs de bits de taille nulle. Ça donne des frissons.
Jens Maurer résume nos discussions. Il écrira la terminologie associée :
struct tag { explicit tag() = default; };
void g() {
tag t0 = tag{}; // Ok
tag t1; // non
tag t2 = {}; // Ok pour un agrégat
}
James Touton revient parmi nous.
Faisal Vali mentionne qu'il faudrait un exemple avec auto pour clarifier le propos.
Hubert Tong a travaillé un exemple pour montrer la déduction de la taille des tableaux :
template <typename T> struct S;
template <typename T, T n> struct S<int[n]> {
using Q = T;
};
typedef S<int[42]>::Q V;
typedef decltype(sizeof 0) V; // OK; T was deduced to std::size_t from the type int[42]
John Spicer suggère une simplification terminologique lors des diagnostics.
On examine quelques cas particuliers qui peuvent mener à des ambiguïtés. Les tailles de tableaux semblent être un cas d'exception intéressant. J'ai manqué un détail ce qui m'empêche de bien relater l'enjeu ici.
Richard Smith revient d'un petit tour chez LWG. Semble qu'ils soient contents de 1776, ce qui permettra d'implémenter correctement optional<T> (voir https://groups.google.com/a/isocpp.org/forum/#!msg/std-proposals/93ebFsxCjvQ/myxPG6o_9pkJ pour des détails)... et vector<T>, qui est techniquement indéfini depuis longtemps si écrit hors de la bibliothèque standard. Ça va soulager bien des gens.
Jason Merrill pense qu'il faudrait couvrir le cas du type auto dans la section sur les déductions. John Spicer pense que rendu là, on a déjà découvert le type effectif.
Daniil Tarakanov soulève la question de auto... mais plusieurs pensent que cette question demande à être examinée par EWG, et peut être construite sur les fondations des travaux en cours. Thomas Köppe : un template <auto> ne pourra correspondre qu'à un template <auto>. Hubert Tong : la terminologie sera très claire en ce sens. Jason Merrill fait remarquer qu'avec template <auto V, auto W> class X{};, dans le type X<2,3>, les types de 2 et de 3 sont des types inventés et ne sont pas, de prime abord, le même type.
Exprimé plus clairement :
#include <type_traits>
template <auto V, auto W>
struct X {
using T = decltype(V);
using U = decltype(W);
};
static_assert(!std::is_same_v<X<2,3>::T, X<2,3>::U>, "");
Il y a des spécialisations possibles :
template <auto v> class Y { };
template <auto* p> class Y<p> { };
template <auto** pp> class Y<pp> { };
template <auto* p0> void g(Y<p0>);
template <auto** pp0> void g(Y<pp0>);
On amène ça en plénière vendredi.
C'est un texte de Hans Boehm qui estime qu'on peut le traiter sans sa présence (il est en train d'animer SG1).
On fait des retouches mineures de forme et de langue. Patrice Roy suggère de scinder la définition de plain lock-free operation du bloc dans lequel cette définition est présentement situé, pour faciliter la lecture et la compréhension.
Les ajustements que nous pouvons faire sont limités, une partie importante du texte de cette proposition tombant sous l'égide de LWG. Toutefois, Hubert Tong fait remarquer que techniquement, la formulation proposée laisse entendre que tout programme C++ est indéfini, ce qui ne convient pas tout à fait (!) alors on reformule au moins le nécessaire pour éviter de telles dérives.
On amènera ça en plénière vendredi.
Pause. Jasette brève avec Jonathan Caves sur le vote à propos du Brexit. Brownies (ça fait du bien, j'avais un peu faim).
Ville Voutilainen nous rapporte que http://open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#1518 n'est pas résolu au goût d'EWG, qui préférerait que transformer ceci :
struct tag { };
... en cela :
struct tag { explicit tag() = default; };
... fasse en sorte que tag ne soit plus un agrégat. Ceci empêchera de faire de la copy-list-initialization avec des étiquettes. Mike Miller trouve que c'est raisonnable; selon lui, la présence d'un constructeur change un peu la nature d'« agrégat » d'un struct. Cependant, les constructeurs =default ne changent pas cette nature; c'est le volet explicit qui fera la différence ici.
Mike Spertus a fait quelques retouches, en particulier l'ajout d'une section pour les deduction guides et une réduction de la portée de ce mécanisme, le temps que l'on puisse vraiment apprécier son impact... qui peut aller très loin, comme on l'a constaté hier dans la rencontre commune entre CWG et EWG.
On examine les changements de grammaire, car il y en a quelques-uns.
Richard Smith soulève le cas suivant :
template <class T> struct V {
using VT = T;
V(VT);
};
V v(3); // ne peut déduire ceci, pour des raisons grammaticales, à cause du using
template <class T>
V<T> f(typename V<T>::VT); // Core Issue 2... c'est un _vieux_ problème
Richard Smith nous invite à examiner Core Issue 2 (sans blagues!). C'est un cas de priorité 1 qui est là depuis très, très longtemps... et qui recoupe directement ce cas. Le T dont parle V<T>::VT est un non-deduced context. John Spicer pense toutefois que c'est autre chose, mais on a quand même un problème. Jason Merrill suggère qu'on se ferme les yeux et qu'on n'en parle tout simplement pas.
Faisal Vali demande pourquoi Issue 2 était numérotée autrement dans le passé. Mike Miller indique que c'est parce que nous avons recommencé la numérotation avec... C++ 98.
On fait plusieurs ajustements ici et là. Truc intéressant : chaque groupe de travail a ses pratiques. CWG travaille surtout sur les premières sections du langage, qui logent les considérations fondamentales. LWG travaille surtout sur les dernières, là où se loge la (vaste!) bibliothèque standard. Chez LWG, outre les fonctions std::move() et std::forward() pour lesquelles std:: est toujours utilisé (ce ne sont pas des points de personnalisation), on omet souvent de préciser les namespaces. Chez CWG, question de perspective, la bibliothèque standard n'est pas un a priori, et std:: est requis.
Richard Smith demande si on veut permettre d'utiliser un deduction-guide en tant que nom de type. C'est une question étrange, mais qui se défend si on examine la grammaire telle qu'elle est écrite.
Richard Smith souligne qu'on ne veut pas nécessairement les mêmes règles que celles applicables aux function templates, même si c'est ce que le texte exprime présentement. À son avis, la règle qu'on veut vraiment est que les types de tous les paramètres soient déductibles. John Spicer penser qu'on n'interdit pas actuellement les paramètres non-déductibles dans ce contexte.
Hubert Tong fait remarquer une incohérence possible entre la grammaire et la sémantique. On échange un peu sur le sujet.
Faisal Vali : si on utilise des template aliases un jour avec ceci (faudra une proposition formelle au préalable), faudra relaxer un peu les règles mises sur la table actuellement. Jens Maurer suggère qu'on y revienne à ce moment, la cour étant pleine cette semaine.
Il y aura un peu de travail de terminologie à faire; nous reverrons cette proposition une dernière fois demain matin.
Thomas Köppe a contacté Hans Boehm et pense qu'on peut clore ce dossier.
On fait des retouches de langue, dans le respect des usages de LWG dans ce cas-ci (ça tombe dans leur région du standard).
La définition de plain lock-free a été logée en prolégomène, ce qui aide à la compréhension du texte.
Il y a confusion sur le sens de signal-safe sur un point : la définition proposée suppose C linkage de même que plein de trucs, et la même proposition inclut le contenu de <limits> qui est truffé de templates. Richard Smith fait remarquer que le volet C linkage est inutile ici, alors on s'en défait tout simplement.
Richard Smith dit qu'il est impossible pour son compilateur d'implémenter ces règles; chaque chargement d'une bibliothèque à liens dynamiques peut avoir un impact dynamique. À son avis, les contraintes décrites par ces règles ne sont pas les bonnes. Clark Nelson fait remarquer que ce nouveau texte ne rend pas la situation pire qu'elle ne l'était au préalable. Richard Smith pense que ça l'empire un peu, mais n'est pas totalement certain. Clark Nelson fait remarquer que signal-safe s'applique aux fonctions, pas aux objets. Richard Smith fait remarquer qu'une fonction signal-safe pourrait provoquer l'initialisation des objets de la bibliothèque <iostream>, par exemple en prenant l'adresse de std::cin (brrrr...).
Hubert Tong fait remarquer que C n'a pas une telle chose que C linkage, ce qui est en soi amusant. Ce sont les paramètres de la fonction qui doivent avoir un C linkage, pas la fonction signal-safe elle-même.
Mike Miller demande si les questions de C linkage sont un problème pour cette proposition. Jens Maurer indique que nous corrigerons ce problème avec une proposition ultérieure. Mike Miller propose une formulation qui fait le boulot pour le moment. Clark Nelson propose un ajustement mineur qui rend la spécification ayant trait aux contraintes d'initialisation dynamique plus claire.
On renvoie ça à LWG pour qu'ils approuvent. On verra ensuite si ce sera porté par LWG ou par CWG.
On arrête vers 17 h 40. Je passe à la chambre pour constater que ma merveilleuse Za a lavé nos vêtements. Ils sont accrochés un peu partout pour sécher.
Je vais rejoindre Za et Cindy au lobby, et nous allons manger dans un chic petit café (salade, bonne bière locale, je me fais gâter par ma belle avec un dessert).
Au retour, notre chambre est archi-propre, outre les vêtements qui sèchent. Un deuxième ménage la même journée. Mystère...
Je descends vers la rencontre de SG14. Michael Wong
nous attend et nous demande d'aller nous chercher une bière (à nos frais )
car il veut une rencontre décontractée.
Michael Wong explique la formation de SG14, l'intégration graduelle du monde de la finance, des banques et des systèmes embarqués, les rencontres in vivo un peu partout sur la planète. Il explique qu'il travaille maintenant dans le domaine des voitures intelligentes, de la vision et des systèmes hétérogènes. Chacun de ces crénaux recoupe les efforts de SG14, en tout ou en partie.
Michael Wong soulève des questions qui préoccupent les gens préoccupés par les considérations de basse latence :
Pablo Halpern parle du rôle des allocateurs, et du fait qu'ils couplent la source de la mémoire avec leur gestion. Ce problème a été mis à l'avant-scène par Andrei Alexandrescu dans une présentation lors de CppCon 2015.
Michael Wong parle des efforts de Guy Davidson et d'Arthur O'Dwyer pour le ring_span (ou le ring_buffer, je ne me souviens plus du nom le plus récent). Neil Horlock et quelqu'un d'autre parlent des enjeux d'un bon tampon circulaire. Ils disent allouer de si gros tampons qu'ils ne sont « circulaires » que de nom (ils n'atteignent jamais la fin!). Hans Boehm demande comment ils interagissent avec le système d'exploitation pour obtenir la mémoire.
Michael Wong parle de non-allocating containers. Quelqu'un dit qu'ils peuvent être très grands. On parle de la difficulté de faire une map sans allocation. Patrice Roy mentionne flat_map, David Stone parle de flat_unordered_map. On échange sur la difficulté des benchmarks.
Michael Wong parle de read/write contention attribute. Il y a des réactions dans la salle.
Michael Wong mentionne le système de std::date de Howard Hinnant, un petit bijou d'optimisation. On parle de la résolution théorique des horloges contemporaines, à la nanoseconde, mais qui ne sont pas si précises que ça en pratique. Detlef Vollman parle de la distinction entre demander le temps au système d'exploitation et celui de poser la question au matériel.
Hans Boehm demande aux gens s'ils préfèrent des files sans verrous ou des files rapides? Neil Horlock parle de basse latence et de basse contention.
Pablo Halpern mentionne les recoupements avec le monde des systèmes embarqués.
Vicente J. Botet Escribá a les mêmes problèmes de son côté, et veux tout ce que Michael Wong a sur sa liste.
Patrice Roy mentionne que pour le monde du jeu, « rapide » signifie « avoir le meilleur pire cas possible ». Dans d'autres domaines, c'est une question de débit, de basse latence, de meilleur temps moyen sur une longue période... Le mot « rapide » pris isolément n'a pas vraiment de sens.
Neil Horlock dit utiliser un coeur dédié pour certaines tâches qui itèrent sans arrêt sur certaines machines. Il dit souhaiter un système de communication inter-processus (IPC). Michael Wong mentionne que ça l'intéresse beaucoup mais que c'est en surplus de l'ensemble des tâches sur le menu. La question du IPC revient à quelques reprises en soirée, d'ailleurs.
Hans Boehm dit que le contrôle sur l'affinité peut être très nuisible; c'est une question d'application. Patrice Roy remarque que le contrôle fin sur les ressources est un thème récurrent chez les participants à SG14, ce qui explique sans doute leur intérêt pour C++.
Quelqu'un mentionne le besoin de meilleurs services de réseautique. Michael Wong demande si le Networking TS convient. Il n'est pas sûr.
Torvald Riegel demande si, pour ceux qui ont des besoins d'IPC, les processus partagent des adresses ou communiquent autrement. On parle de Zero Copy. Torvald Riegel dit que si on veut permettre les échanges directs de données, faudra toucher au modèle mémoire; s'il nous faut une abstraction pour des canaux, c'est une autre histoire.
Quelqu'un parle du High Performance Computing, ou HPC. Dans son domaine, ils s'éloignent de l'IPC et passent de plus en plus vers des systèmes de communication point à point. La raison est le coût des accès en mémoire. Les coûts des accès à des régions de mémoire NUMA est important, et la localité est essentielle.
Hans Boehm dit que le
modèle mémoire a été pensé de prime abord pour être étendu à de la mémoire partagée,
ce qui le rend moins préoccupé que Torvald Riegel sur ce
point. Il mentionne toutefois qu'il faut penser à ce qu'on veut mettre dedans (on oublie les
vtbl ).
Roger Orr parle de Base Address-Insensitive Data Types;
je ne connais pas ce concept mais c'est intrigant alors je vais lui en parler
demain.
Vicente J. Botet Escribá parle d'utiliser l'ensemble des ressources pour maximiser le débit.
Quelqu'un parle de petits vecteurs (clump?) et de petites matrices pour les calculs physiques. Un type de données tensor serait important. Neil Horlock parle pour sa part de grandes matrices. Patrice Roy dit que les petites matrices et les grandes matrices ne seront pas optimisées avec les mêmes techniques. Il mentionne aussi l'importance du Heterogeneous Computing. Michael Wong fait valoir que c'est la priorité des priorités à ses yeux.
Certains veulent faciliter le nommage des choses, pour utiliser plusieurs compilateurs à partir d'un même ensemble de fichiers sources. Autrement dit, une ABI commune. Ça faciliterait le développement hétérogène. Sans ABI commune, en particulier, il est difficile de s'échanger des λ. Neil Horlock veut distribuer le traitement sur une masse de noeuds.
J'ai passé pas mal de temps sur la scène à partir d'ici, donc il me manque 30-40 minutes de prise de notes. Beaucoup de trucs :
Gor Nishanov prend le plancher pour parler des coroutines. Il a le même code dans son exemple pour les versions sync et async, en utilisant un type de retour future<int> pour le async et un expected<int> pour le sync. Gor Nishanov présente expected<T> comme une future<T> qui est toujours prête.
Gor Nishanov explore d'autres syntaxes, comme un auto r = try f(); au lieu d'un auto r = await f(); ce qui rapprocherait C++ de Rust ou de Swift.
L'exécution d'une coroutine peut être annulée. Gor Nishanov dit que l'annulation des coroutines a été pensée pour permettre à un consommateur de données d'un générateur d'écrire un truc comme :
for(;;) {
auto r = await generer();
utiliser(r);
if (bla) break; // sortir sans pénalités
}
Gor Nishanov dit qu'il
fera de meilleures coroutines avc
LLVM, car avec MSVC,
il doit prendre soin de ses clients
La semaine suivante, Gor Nishanov m'a écrit un petit mot indiquant que ce que j'avais noté de portait pas bien l'idée qu'il voulait véhiculer. Il m'a suggéré ceci :
generator<int> numbers() {
int i = 0;
for (;;) co_yield i++;
}
int main() {
for (auto v : numbers())
if (v > 10)
break; // should cancel the coroutine cheaply without an EH overhead
}
Il a ajouté ceci :
Note that the coroutine above will keep running forever unless cancelled. Every suspend point, such as co_yield encodes two possible resumption paths. One is normal, another is cancel. You trigger the normal resumption via coroutine_handle::resume() and you trigger cancel with coroutine_handle::destroy().
Voilà, ajustement fait.
Michael Wong voit les coroutines comme une alternative intéressante aux exceptions.
Gor Nishanov parle ensuite des Reactive Streams. Ils ont aussi l'annulation et le backpressure. Les données entrent, on les consomme, on insère des opérateurs pour réagir à ce qui entre. Le timeout est modélisé comme un opérateur.
Gor Nishanov nous donne une démo avec de la musique... Il a utilisé un flux pour les données de mouvement de la souris, un pour fixer les événements et ne garder que la position, une pour ne garder que les valeurs distinctes, un pour introduire un délai, et un pour dessiner les points. Il fait ensuite une autre démo avec du Drag & Drop de texte, plus complexe mais pas tant que ça. Propre.
Patrice Roy lui mentionne la présentation de Sumant Tambe à CppCon 2015, qui a utilisé RxCpp pour une application complexe de type IoT. Patrice Roy indique aussi que ce type de système est très bon pour certains types d'applications, surtout pour optimiser le cas moyen, mais moins bon pour les jeux car le pire cas est difficile à mesurer, étant dépendants du débit source.
Quelqu'un mentionne que pour les FPGA, la programmation réactive est excellente. Gor Nishanov mentionne que c'est très léger comme manière de programmer, et qu'il n'a dans son code que des templates éminemment optimisables, sans le moindre appel indirect.
Hans Boehm dit qu'une proposition sur les Streams sera amenée à SG1, probablement demain.
Autre grosse journée, donc. Je me suis permis de regarder le plus récent épisode d'une émission avec ma belle, puis j'ai travaillé un peu avant d'aller me coucher vers 0 h 45.
Demain, ça risque de brasser : rencontre de CWG en début de journée, caucus de la délégation canadienne (nous sommes neuf ici, si j'ai bien compté) pour dîner, puis le pré-vote en après-midi pour voir comment s'articule le volet plus politique des travaux. Le vote officiel de C++ 17 se tiendra samedi, mais c'est demain qu'on verra comment sont placés les pions...
Bonne Fête nationale!
Je me lève, je prends ma douche, et j'examine brièvement les nouvelles (du 23 juin quelques minutes avant minuit, décalge horaire aidant) à la maison pour constater :
Ici, c'est une journée costaude où, discrètement en comparaison avec ces événements de grande envergure, nous allons prendre des décisions qui influenceront les destinées de tas de gens (directement ou indirectement, en fait, la vie de presque tout le monde sur la planète et des humains qui se promènent en périphérie). Espérons que nous saurons faire des choix à la fois courageux, en prenant de bons risques, et raisonnés, en ne plongeant pas tête baissée dans des projets qui se transformeraient en cul-de-sac
On reprend la proposition de Mike Spertus.
Mike Spertus est allé bavarder avec Ville Voutilainen et les questions de déductibilité semblent réglées.
On fait des retouches linguistiques mineures.
Fedor Sergeev suggère d'ajouter une référence croisée de §14.1 vers §14.9. Mike Miller pense que c'est une bonne idée.
Daniil Tarakanov se questionne sur la distinction de deduction-guides les uns les autres, et sur la sélection du constructeur approprié. Jens Maurer signale qu'une bonne implémentation pourrait économiser du temps de traitement en recyclant les fruits de cette déduction, mais Mike Spertus dit de ne pas faire ça à cause des possibles spécialisations. Mike Spertus dit que c'est le design attendu.
On amènera ça en plénière cet après-midi.
Richard Smith nous informe que les variables inline constituent un breaking change dans des cas où il y a une interaction avec constexpr. On a donc un changement à §7.1.5 p1. Ça semble être une bonne chose.
Hubert Tong pense que la proposition soumise n'est qu'une demi proposition. On fait remarquer qu'une autre proposition, P0298, complète la présente.
Richard Smith fait remarquer qu'il manque un détail sur l'utilisation de tableaux et std::byte en lieu et place de tableaux d'unsigned char. On parle de p0137r1 où une mention de byte serait la bienvenue.
Jens Maurer demande si on doit présenter les deux propositions séparément ou en même temps. Hubert Tong pense qu'il y a une dépendance, et qu'il aurait été préférable de faire adopter / rejeter les deux en bloc. Neil Macintosh est à l'aise de réaliser la fusion ce matin.
Neil Macintosh dit qu'une insertion de ce type dans <cstddef> est possible selon LEWG. Richard Smith indique que ça peut poser problème de cohérence avec C. C'est plus un problème dans la talle de LWG cependant.
Hubert Tong mentionne une préoccupation terminologique, à l'effet que l'une des alternatives parle de signedness alors que ce n'est pas pertinent. Neil Macintosh dit que sa préférence tient à une implémentation par strong typedef passant par un enum, mais que LEWG voulait laisser le choix à LWG.
Jens Maurer : hormis un transtypage explicite, on ne peut faire de l'arithmétique sur un std::byte.
Richard Smith note que les deux approches dans le document reposent sur une extension spécifique à Microsoft. Neil Macintosh corrigera.
Thomas Köppe suggère que les endroits où std::byte est mentionné, des références soient ajoutées vers la section de la bibliothèque qui le décrivent, du fait que ce n'est pas un type primitif.
On fait des retouches de langue mineures. Neil Macintosh est un très chic type.
Fedor Sergeev demande pourquoi on a un cas spécifique pour les champs de bits. Il pense que ce cas particulier est couvert par le cas général qui précède. Jens Maurer dit percevoir le bitfield-ness comme une propriété booléenne d'un type, et dit que ça peut jouer des tours avec l'opérateur ternaire. Daniil Tarakanov trouve que ce passage pourrait être plus clair. Richard Smith dit qu'on a des cas semblables ailleurs, mais indique que pour les attributs d'instance on ne fait pas de distinction pour les champs de bits. Le problème est qu'un truc comme ceci
auto f() {
struct X { short a : 5, b : 11; };
return { 2, 3 };
}
void g() {
auto [ x, y ] = f(); // <--
}
...fait en pratique de x et de y des sortes de références sur des champs de bits (chose qui n'existe pas dans le langage). Jens Maurer dit qu'il est inconfortable avec l'idée de parler de x et de y comme des variables en bonne et due forme.
John Spicer estime que le nombre d'exemples est insuffisant. Roger Orr suggère un exemple avec un tableau.
Hubert Tong propose un exemple préoccupant :
typedef int R;
const int x = 3;
void f() {
const int R[x] = { 0 };
}
Il se demande si R dans f() est un tableau. Semble que oui, avec la grammaire que l'on développe. Il y a des soupirs de soulagement dans la salle.
Richard Smith soulève la question des union anonymes vides. Jens Maurer dit qu'il préférerait ne pas s'en occuper maintenant et accueillera une proposition sur le sujet si quelqu'un prend la peine d'en écrire une. Herb Sutter dit qu'il ne s'en fait pas avec ça; l'objet n'avait pas de nom a priori alors... Jens Maurer note qu'on ne saurait pas quel membre on a copié, mais en même temps si quelqu'un se sert de ce mécanisme sur un union, mieux vaut pour elle ou lui d'accéder au membre actif seulement. Herb Sutter dit qu'on pourra étendre le mécanisme (récursivité des copies et tout le tralala) dans le futur.
Roger Orr suggère d'ajouter une référence à tuple_size dans le texte.
Richard Smith demande, dans le cas où on retourne un struct S, comment seront séquencés les appels à get<i>(S). On présume que ce sera du premier au dernier.
On se demande si on retourne techniquement des références ou des copies, donc quel sera le comportement de decltype(x) sur un membre x retourné par Structured Binding. Herb Sutter dit qu'il faut que ce soit spécifié mais que c'est plus ou moins important car ce n'est pas un cas d'utilisation de ce mécanisme.
Patrice Roy pose la question de l'exemple suivant :
auto f() {
int x = 3;
return x;
}
auto g() {
struct { int n = 3; } x;
return x;
}
auto x0 = f();
// auto [x1] = f(); // illégal
auto [x2] = g();
static_assert(is_same_v<decltype(x0),decltype(x2)>,"");
Hubert Tong dit non; on ne peut faire de Structured Binding sur un scalaire.
Mike Miller reçoit une question d'EWG qui questionne le comportement de get<I>(obj) en lien avec des Proxy Objects. Je réfléchissais à autre chose alors j'ai manqué une subtilité de l'argumentaire.
On prend une pause vers 10 h 15. Les bouchées offertes par l'hôtel sont très bonnes, comme toujours.
J'échange un peu avec Roger Orr pour comprendre son idée de Base Address-Independent Data Type, mentionnée à la rencontre de SG14 hier soir. Il me parle d'une paire où les données seraient placées relativement à une adresse de base, et où cette dernière serait relocalisable. Il faudrait bien sûr, pour faire communiquer des processus entre eux, être prudents sur le contenu de ces objets.
Clark Nelson jonglait avec l'idée de débuter plus tôt cet après-midi. Nous étions ouverts, mais Herb Sutter nous a rappelé à l'ordre : on n'a pas le droit de changer l'agenda comme ça, car des gens pourraient alors manquer un vote important et nous blâmer – avec raison. On commencera donc à l'heure, quitte à finir tard. Il y a quelques dossiers très contentieux chez CWG, mais il en circule des rudes ailleurs aussi, alors il y aura des bras de fer politiques tantôt.
Mike Spencer vient nous voir avec le nom « choisi » par LEWG pour remplacer is_contiguous_layout. Ce nom sera :
Ce sera has_unique_object_representations. C'est un dossier porté par LWG.
Hubert Tong revient sur la question des union anonymes. Les règles de capture des λ peuvent servir d'inspiration. John Spicer dit qu'il est raisonnable de pouvoir les capturer pour les passer en paramètre à des fonctions. Jens Maurer dit que pour une capture par valeur, on peut copier la bête au complet. John Spicer est inconfortable avec l'idée de capturer un champ de bits par référence. Hubert Tong indique que la syntaxe sur la table pour les Structured Bindings, il n'y a pas de syntaxe pour capturer par référence. Cette capture est en fait une réécriture qui fait de la magie. Jens Maurer demande si on doit exclure les champs de bits des cas de capture implicite par référence. Hubert Tong pense que si. On élargira le champ des possibles éventuellement si on le juge possible et utile.
Jens a ajouté des exemples :
auto f() -> int(&)[2];
auto [ x, y ] = f(); // x and y refer to elements in a copy of the array return value
auto& [ xr, yr ] = f();
On a du neuf avec les champs de bits ici. Par exemple :
struct S { int x1 : 2; volatile double y1; };
S f();
const auto [ x, y ] = f();
Jens Maurer explique que la mécanique est :
On amène ça en plénière tantôt.
Thomas Köppe présente son idée, qui permet plus aisément de créer des temporaires de courte durée dans un if.
John Spicer demande si on peut encore déclarer des trucs dans le bloc de test de condition.
Daniil Tarakanov mentionne qu'on peut mettre une expression quelconque dans le init-statement. La réponse est oui.
Thomas Köppe dit que l'idée est vraiment de contrôler la complexité.
On fait un tour de table, et tout le monde veut ce feature depuis toujours.
Patrice Roy demande si l'initialisation dans un if constexpr est spéciale. Thomas Köppe dit non, c'est la condition qui doit être évaluée à la compilation.
On amène ça en plénière tantôt.
Nous avons traité beaucoup, beaucoup de propositions cette semaine. Il est 11 h 40 et nous allons essayer de traiter des issues pour le petit peu de temps qu'il nous reste.
On essaie de s'assurer que l'initialisation explicite des agrégats est claire. On s'assure que la définition soit la bonne, mais il y a des subtilités. Richard Smith demande si une classe qui a un constructeur de copie = delete; demeure un agrégat.
On amène ça en plénière tantôt.
Nous arrêtons vers 12 h 5 pour dîner. Michael Wong nous a demandé de nous réserver une table au resraurant de l'hôtel pour tenir une sorte de « caucus canadien », dans le but de regrouper nos perceptions et de dégager une position canadienne officielle, de mieux comprendre les enjeux, de partager nos impressions des événements vécus selon les groupes de travail, et de manière générale pour discuter stratégie sur le plan politique. Nous en avons profité pour clarifier certains aspects plus scientifiques au passage, dégager la rumeur et mieux comprendre les enjeux pour les dossiers que nous avons moins suivis.
Une fois ces considérations traitées, nos discussions ont porté sur la rencontre du comité à Toronto à l'été 2017. Ce sera une rencontre importante, car si nous votons aujourd'hui ce qui fera partie de C++ 17, c'est à la rencontre de Toronto que le standard devrait devenir officiel, une fois les commentaires des pays reçus et traités.Nous avons donc discuté de logistique, de financement, logement, transport, etc. Nous avons aussi pris le temps d'échanger socialement. Nous sommes sept ici finalement, soit Michael Wong, Hubert Tong, JF Bastien, Duncan Exon Smith, Tony Van Eerd, Botond Ballo et moi-même. Ça nous fait une bonne équipe.
Place en pléniere. Je prends des nouvelles de Neil Macintosh, qui n'est pas arrivé à temps pour officialiser std::byte pour C++ 17. C'est triste. Il le prend bien, mais je pense qu'il est déçu. Je peux le comprendre : c'est une bonne proposition, solide et utile, mais il y avait tant à faire qu'on n'a pas réussi à franchir la dernière étape avec celle-là.
Gor Nishanov vient dire bonjour. Il doit passer quelques jours à Montréal cet été, car sa fille vient dans un camp de ballet pour trois semaines, et il se cherchera des trucs à faire. Je vais regarder avec Za ce qu'on peut faire pour s'assurer qu'il apprécie son séjour.
On se prépare pour la plénière. Je m'asseois près de Jonathan Caves, Walter E. Brown et Jens Maurer, à l'avant de la salle, pour faciliter les interventions (j'ai quelques trucs à faire). Tristement, les tables font « scouic scouic » quand je tape au clavier, mais on va devoir « faire avec ».
Les travaux commencent à 14 h 30.
Herb Sutter nous dit que les gens qui nous ont filmés tout au long de la semaine nous offrent de retirer notre visage si on le souhaite. Cet après-midi, on a entre 40 et 50 propositions à voter alors on se met au boulot. Notez que je serai succinct ci-dessous, pour éviter de donner dans le nominatif (c'est parfois rude) et parce qu'on parle d'une séance de tout près de cinq heures de vote et de débats à plus de cent personnes.
Ville Voutilainen nous informe qu'il y aura très peu de restaurants ouverts en fin de semaine, dû à une fête nationale ici. Le restaurant de l'hôtel fait un souper spécial de 17 h 30 à 19 h 30, ce qui peut aider puisqu'en ville, les options seront limitées.
On fait ensuite le point sur les travaux des groupes de travail et des groupes d'étude au cours de la semaine. C'était une semaine spéciale, tout le monde essayant de fermer les dossiers ouverts au plus tard à Jacksonville en vue d'en arriver à un C++ 17 qui serait feature-complete aujourd'hui – en fait, techniquement : demain, car les votes du vendredi sont indicatifs, pour évacuer les dossiers qui ne font pas consensus et éviter que les votes du samedi mènent à des situations politiques intenables. Le vendredi, nous faisons ce qu'il faut pour que le samedi, les votes soient une formalité.
Michael Wong fait le point sur SG5. Pas de rencontres cette semaine mais les téléconférences se poursuivent. Michael Wong nous informe GCC 6.1 supporte le TS de mémoire transactionnelle. Bravo!
Walter E. Brown dit que SG6 ne s'est pas réuni cette semaine.
Chandler Carruth fait le point sur SG7 qui a eu une longue rencontre de soirée, Une présentation intéressante sur l'introspection a été faite, une rétroaction a été donnée, et on attend une proposition qui y fera suite. En réponse à Bjarne Stroustrup, Chandler Carruth explique que le gros design issue est de faire de la réflexivité sur des trucs comme typedef, qui ne font pas partie du système de types, et les objets « anonymes » comme les λ, les struct anonymes et les union anonymes. Ville Voutilainen demande où on en est avec l'exploration des membres privés. On veut pouvoir le faire mais ça n'a pas avancé tant que ça.
Clark Nelson dit que SG10 ne s'est pas réuni, mais qu'ils font beaucoup de téléconférences. Il fait savoir par contre que SD6 chez isocpp.org, de SG10, est un excellent endroit pour se tenir au courant de ce qu'il y aura dans C++ 17. C'est dans SD6 qu'on trouve tous les documents adoptés pour le standard.
Gabriel Dos Reis dit que SG12 ne s'est pas réuni cette semaine.
Michael Wong fait le point sur SG14. Une rencontre de soirée s'est tenue, il y avait beaucoup de participants. Deux propositions ont été livrées. Le milieu financier, ceux des systèmes embarqués et de la bourse participent de plus en plus à ce groupe. On inclura des travaux en collaboration avec SG1, qui alimente en partie SG14. Herb Sutter demande si SG14 tient d'autres rencontres; Michael Wong parle d'une rencontre en Europe sous peu, puis CppCon 2016, puis Meeting C++ en décembre.
Hans Boehm dit que SG1 s'est rencontré toute la semaine. Certains dossiers ont bloqué, dont joining_thread; Hans Boehm s'attend à des NB Comments. Le texte portant sur les signaux a été nettoyé. On aura des motions pour améliorer les politiques d'exécution, améliorer memory_order_consume, intégrer les exceptions et le parallélisme (ça a brassé, apparemment), et la terminologie sur les garanties de progrès. Ils ont aussi parlé de Concurrency v2 et de Parallelism v2, deux TS. Ils auront des propositions sur les nombres à virgule flottante atomiques, de nouveaux outils de synchronisation, etc. Bjarne Stroustrup demande où en est future.then; Hans Boehm dit que c'est dans Concurrency, et qu'il n'y avait pas de propositions pour C++ 17.
Pour EWG, Ville Voutilainen dit qu'ils ont terminé le design des facilités de C++ 17, et alimenté CWG. La liste des trucs est longue. Les coroutines ont été discutées mais pas complétées. Le pattern matching avance. Quelques trucs ne passeront pas dans C++ 17, incluant comma elision et comma deletion, une modernisation des déclarations using pour les associer aves des Packs, et les designated initializations. Parmi les trucs qui n'ont pas passé, on compte regular void, operator.() (Gabriel Dos Reis dit qu'il ne pense pas que ça fut rejeté; Ville Voutilainen dit qu'on s'attend à ce que ça revienne; Bjarne Stroustrup dit que ça a été mis de côté quand CWG a trouvé un véritable bogue qui demandera du temps à régler) et les λ dans un contexte non-évalué. On remercie Andrew Pardoe pour avoir tout noté, et on remarque que la relation entre EWG et CWG fut smooth as silk.
Pour LEWG, Jeffrey Yasskin devant s'absenter d'Issaquah, ils ont essayé quelques remplaçants et ont sélectionné Neil Macintosh comme Chair pour cette rencontre. Pour les Structured Bindings, à court terme, on ne fait rien de spécial en lien avec la bibliothèque. On devient plus confortable avec le temps qui passe pour ce qui est d'envoyer les trucs directement au IS sans passer par un TS. Mercredi, ils ont travaillé sur le Graphics TS et il y a de l'espoir pour Issaquah. LEWG a envoyé 17 propositions à LWG. Pour C++ Next (probablement C++ 20), une dizaine de propositions ont avancé. Il remercie les scribes. Ville Voutilainen demande si make_array() a été examiné, et la réponse est non.
Pour CWG, Mike Miller dit avoir apprécié la collaboration entre CWG et EWG cette semaine. On souligne (avec raison!) le travail colossal de Jens Maurer. On n'a pratiquement pas fait d'issue processing, étant submergés dans le travail pour C++ 17. On les classera demain matin en vue d'Issaquah. Nicolai Josuttis demande si ces issues pourraient se retrouver dans C++ 17. Mike Miller dit que oui. Herb Sutter dit qu'on a encore un an pour traiter des issues; ce qu'on fait cette semaine, c'est rendre C++ 17 feature-complete. Peter Sommerlad dit qu'il souhaitait voter sur le futur WD. Herb Sutter dit qu'on ne planifie pas travailler sur deux WD en même temps. Alisdair Meredith souhaite qu'on ne dérape pas dans cette direction maintenant. Ville Voutilainen demande combien de ballots avec commentaires nous aurons. Herb Sutter dit qu'on aura le CD, puis le DIS, puis l'IS. CWG a traité toutes les propositions pending pour C++ 17, de peine et de misère. Il y en avait 14 qui remontaient à Jacskonville. Le cas d'operator.() est revenu sur ses pas pour questions de design. Deux propositions n'étaient pas nécessairement pour C++ 17 mais ont été traitées (les if avec initialisations, et les Structured Bindings). Ville Voutilainen dit que ces propositions ont été envoyées à CWG avec mention « schedule as you see fit », mais CWG a réussi à les faufiler. Quelqu'un demande si CWG a discuté des using declarations, mais Mike Miller dit ne pas les avoir vu passer (Jens Maurer dit qu'on n'aurait pas pu de toute manière; on a dépassé le temps alloué de cinq minutes). Bjarne Stroustrup rappelle, gracieusement, que CWG a trouvé un vrai problème avec operator.(), ce que Mike Miller dit apprécier. Mike Miller dit que CWG a eu le temps de traiter un issue, pour aider LWG (qui disent merci!). Mike Miller liste ensuite les (nombreux) dossiers traités. Deux ont été cheminés à LWG qui ont manqué de temps, soit la suppression des spécifications d'exceptions et le type std::byte. CWG n'a pas eu le temps de traiter quelques dossier sur les concepts et les coroutines, tristement.
On y va avec les votes :
Dossier | Vote | Remarques |
---|---|---|
Le Defect Reports de P0384R0 | unanime | |
Function concepts not allowed to be declared in more than one TU | unanime | |
Using attribute namespaces without repetition | unanime | |
Dynamic memory allocation of over-aligned data | unanime | |
Template argument deduction for class templates | consensus |
On a retiré ce qui était controversé, on n'a rien ajouté. L'opposition avait trait au modèle de déduction préconisé |
Declaring non-type template parameters with auto | unanime | |
Wording for guaranteed copy elision through simplified value categories | unanime |
Ceci retire l'une des rares optimisations qui n'était pas as-if du langage, et en fait quelque chose d'obligatoire, sur lequel les programmeuses et les programmeurs peuvent compter |
Core Issue 1776: Replacement of class objects containing reference members | unanime |
C'est std::launder() et autres; ça permet d'implémenter optional<T> et amis sans donner dans le comportement indéfini |
Refining Expression Evaluation Order for Idiomatic C++ | consensus, mais sans l'ordonnancement imposé de l'évaluation des paramètres des appels de fonctions dans un ordre fixé |
Sans surprises, le truc qui m'agace en agaçait d'autres. J'ai parlé un peu fort, mais d'autres comme Chandler Carruth et Jason Merrill aussi. Évidemment, c'est partagé, sinon on ne serait pas là... La version « entière » était à égal pour/contre, et un peu moins de neutres. L'ordre d'évaluation est non-spécifié mais il n'y a pas d'enchevêtrement. Autrement dit, dans , l'ordre d'évaluation de et de demeure non-spécifié, mais il n'y a pas d'enchevêtrement, ce qui est à mon avis la meilleure option pour rester sain d'esprit tout en gardant la capacité de déboguer les programmes sans avoir à examiner dans le détail le code source de chaque fonction appelée. |
Proposed wording for default comparisons | pas de consensus, plus de contre que de pour |
Celle-là est extrêmement controversée, pour un tas de raisons techniques comme politiques, et a fait parler les gens toute la semaine. Entre autres choses, le consensus général semblait être d'en faire un opt-in, donc de les générer sur demande, mais la proposition amenée pour vote était un opt-out, ce qui demandait aux gens de demander explicitement d'y être soustrait. |
Standard and non-standard attributes | unanime | |
constexpr if: A slightly different syntax | consensus, assez fort d'ailleurs, mais avec plusieurs abstentions. Cependant, il y a opposition d'un pays, et apparence (c'est pas clair) d'un deuxième, alors il se peut qu'on ait des NB Comments |
Il y a de la controverse ici, car il y a un sentiment que la solution générale serait les concepts, mais nous ne les avons pas encore. Certains craignent que ceci ne ralentisse l'adoption de trucs plus importants. |
On a pris une pause à ce stade, vers 16 h 30. Il y avait de la tension dans la salle alors ça a bien tombé. Je vais voir Za et Cindy, qui profitent de la terrasse. On parle brièvement de la logistique du souper, avec la ville qui se vide et le buffet proposé à l'hôtel, mais il n'est pas clair que nos travaux vont se terminer avant 19 h au ryhtme où ça progresse. |
||
Forward progress guarantees: Base definitions | unanime | |
Forward progress guarantees for the Parallelism TS features | unanime | |
Inline Variables | consensus, mais avec beaucoup d'abstensions et risque de retour par des National Bodies |
Il y a de la résistance; plusieurs n'aiment pas cette fonctionnalité, d'autres trouvent que ça résout un vrai problème; le problème est que, si on avait les modules, on n'en aurait probablement pas besoin. |
Introducing the term 'templated entity' | unanime | |
Proposed wording for structured bindings | consensus, plusieurs neutres |
Certains trouvent que c'est un gros changement arrivé un peu tard dans le processus, mais on en avait déjà parlé à Kona |
Selection statements with initializer | consensus très fort |
Presque tout le monde veut pouvoir faire ça depuis toujours |
Core issue 1518: Explicit default constructors and copy-list-initialization | unanime |
Marshall Clow prend le plancher. Il explique que LWG a traité 39 propositions sur 41. Il mentionne aussi qu'il compte organiser une rencontre pour LWG seulement à Chicago en 2016, pour réduire la pile de dossiers à traiter. Cette rencontre se tiendra sur cinq jours.
Dans certains cas, Marshall Clow a groupé les propositions pour faciliter leur adoption en bloc. À mon grand soulagement, il a eu la sagesse de le faire dans les cas qui ne prêtaient pas à controverse, ce qui nous a permis d'avancer un peu,
LWG – Motions | Vote | Note | |
---|---|---|---|
Bloc 1 |
|
unanime | |
Bloc 2 |
|
unanime | |
Bloc 3 |
|
unanime | |
Bloc 4 |
|
unanime | |
Bloc 5 |
|
unanime |
Celles-ci sont des Priority 1, qu'il fallait réparer avant de publier le standard |
Bloc 6 |
|
unanime |
Celles-ci sont devenues « ready » cette semaine |
Les motions de LWG proposées par la suite devaient être traitées une à une, certaines étant plus sujettes à controverse, méritant des explications ou une présentation plus personnalisée. Chacune commence par « Move we apply to the C++ Working Paper the Proposed Wording from... », que je n'ai pas répété par souci de concision,
Dossier | Vote | Remarques |
---|---|---|
p0063r3, C++17 should refer to C11 instead of C99 | consensus |
Semble que ce fut surtout éditorial. Walter E. Brown dit que Clark Nelson a fait un travail colossal. C a une annexe, l'annexe K, qui contient des fonctions à support optionnel. Thomas Köppe dit qu'on a plus ou moins le choix, car il n'y a qu'un seul standard C, soit le plus récent |
p0175r1, Synopses for the C library | unanime |
Changement éditorial |
p0088r3, Variant: a type-safe union for C++17 | unanime |
Ce type, important et attendu, est sujet à débats depuis des années. Son adoption unanime s'est faite à l'étonnement général! |
p0307r2, Making Optional Greater Equal Again | consensus | |
p0393r3, Making Variant Greater Equal | unanime | |
p0032r3, Homogeneous interface for variant, any and optional | consensus |
De la résistance sur le fait que l'interface proposée demande des connaissances avancées pour certaines manoeuvres, et qu'on parle d'un type vocabulaire. Majorité d'abstentions, à peu près trois pour pour chaque contre pour le papier tel quel, semblable pour le papier avec retrait de techniques uniformes d'insertion. Pas de consensus. Oups! On refait un vote à trois options, soit le papier tel quel, le papier amputé, et rien du tout. Le papier tel quel l'emporte. Jonathan Wakely invite les NB Comments, c'est un bon candidat |
p0067r3, Elementary string conversions | unanime | |
p0254r2, Integrating std::string_view and std::string | unanime | |
N4524, If vector::reserve(n) reallocates, capacity()==n | rejeté |
Les optimiseurs veulent de la liberté. Les gens de systèmes embarqués veulent du contrôle. Jonathan Wakely a une alternative mais c'est pas prêt. En retour, présentement, ce que demande la proposition est ce que font les implémentations; le rejet tient au fait que les gens craignent de se peinturer dans un coin. Il n'y avait pas de bonne réponse claire ici, alors espérons que la proposition de Jonathan Wakely tranchera le noeud gordien |
p0258R2, has_unique_object_representations | unanime | |
p0040r3, Extending memory management tools | consensus |
Une première proposition adoptée qui provient des travaux de SG14. Bravo Brent Friedman! |
p0084r2, Emplace Return Type | unanime | |
p0302r1, Removing Allocator Support in std::function | unanime |
Un truc qui n'a jamais fonctionné en six ans. L'enfer est pavé de bonnes intentions |
p0083r3, Splicing Maps and Sets | unanime | |
p0181r1, Ordered by Default | unanime | |
p0163r0, shared_ptr::weak_type | unanime | |
p0209r2, make_from_tuple: apply for construction | unanime | |
p0295r0, Adopt Selected Library Fundamentals V2 Components for C++17 | unanime |
On a maintenant un PPCD et un PPCM tous deux constexpr sous la forme de std::gcd() et std::lcm() |
p0174r2, Deprecating Vestigial Library Parts in C++17 | consensus |
J'ai levé le ton à cause de la procédure omnibus mais je n'ai pas milité pour un rejet. C'est une bonne proposition, mais qui met trop de trucs dans un même panier, de telle sorte que tous y trouveront quelque chose d'inconfortable. Les procédures omnibus, c'est mauvais au parlement, et c'est mauvais dans ce genre de comité aussi |
p0337r0, Delete operator= for polymorphic_allocator | unanime | |
p0358r1, Fixes for not_fn | unanime | |
p0219r1, Relative Paths for Filesystem | unanime | |
p0392r0, Adapting string_view by filesystem paths | unanime | |
P0394r4, Hotel Parallelifornia: terminate() for Parallel Algorithms Exception Handling | consensus |
Controversé, car arrivé tard et changement de direction radical, mais je dois admettre que je pense que l'auteur a raison sur le fond : c'était probablement la meilleure solution à court terme si on veut en arriver à une solution générale à moyen terme |
p0336r1, Better Names for Parallel Execution Policies in C++17 | unanime | |
p0371r1, Temporarily discourage memory_order_consume | unanime |
Ici, « temporairement » signifie au moins jusqu'au prochain IS |
p0346r1, A <random> Nomenclature Tweak | unanime |
Un générateur était bien mal nommé |
p0180r2, Reserve a New Library Namespace for Future Standardization | consensus |
On réserve une plage de noms (tout ce qui est stdX où X est un entier positif : std2, std43 et std135711) pour les mises à jour du standard. C'est pas terrible mais c'est ce qu'on a trouvé de mieux à court terme, et on pourra le changer par un NB Comment si on a un coup de génie dans la prochaine année. Quelqu'un a demandé le vote; aucune idée pour quelle raison. |
Ne restait qu`'à voter des gens pour valider le CD et faire le suivi, ce que nous avons fait en mettant les Chairs sur le dossier (Mike Miller, Marshall Clow, Jeffrey Yasskin et Ville Voutilainen). Ouf. On a terminé. Il est 19 h 15.
C'est vrai que c'est vide en ville quand c'est fête ici. Il y a des restos ouverts, mais peu. J'aurais bien pris une bière mais les épiceries sont fermées. J'ai pris un sandwich croissant et saumon au marché public en face; il y avait de la dijonnaise, une sauce que les gens du coin aiment manifestement beaucoup (il y en avait sur la pizza et dans la plupart des sandwich que j'ai mangés cette semaine). En arrivant à l'hôtel, revenant de ma petite marche, j'ai demandé aux gens du lobby si je pouvais acheter une bière et la ramener à ma chambre pour la déguster en travaillant, et ça n'a pas posé problème (outre le fait qu'à l'hôtel, c'est dispendieux).
Za et Cindy devaient aller faire du vélo mais il n'y en avait plus de disponible. Nous sommes allés prendre une marche le long de la rivière, puis un peu en ville (car ici, le soir, même s'il fait clair, il y a beaucoup de moustiques aux abords de l'eau). Nous avons fait un peu de géocaching infructueux, pris un verre dans un pub sympathique (des collègues de WG21 sont venus faire de même alors qu'on sortait), nous sommes allés à la piscine (moi et Za) et au gym (Cindy) de l'hôtel (j'ai trempé mes pieds dans l'eau froide, un petit plaisir de la vie) et je me suis couché tôt (22 h 30-22 h 45). Le vendredi soir, les semaines de rencontre du comité, je suis toujours brûlé, et ce soir ne fait pas exception.
Un dernier coup de barre à donner. J'ai eu des nouvelles du sympathique Gor Nishanov, qui souhaite venir faire un tour à Montréal cet été et aimerait avoir des suggestions de trucs à faire. Za, Cindy et moi-même allons prendre une pâtisserie au marché public, et je rejoins CWG pour que nous nous mettions en marche.
Jens Maurer nous informe qu'il n'y a pas de service d'autobus pour atteindre l'aéroport, dû aux fêtes ici.
Thomas Köppe me montre quelques exemples sympathiques de code C++ 17 qu'il a concoctés depuis hier. C'est un langage bien intéressant qui se dessine devant nous.
On se met en marche vers 8 h 40. Mike Miller nous informe que nous avons beaucoup de retard dans les issues processing. À Issaquah, nous devrions faire essentiellement du travail de ce type. Mike Miller soulève la possibilité de tenir une rencontre in vivo de CWG d'ici Issaquah, mais plusieurs (dont moi) ne peuvent envisager ajouter un voyage à l'agenda, alors des téléconférences plus fréquentes sont à prévoir. On essaiera de faire une heure de traitement d'issues suite à la plénière cet après-midi pour faire avancer des dossiers.
Mike Miller indique que la proposition sur l'ordre d'évaluation des sous-expressions dans un appel de fonction, adoptée hier, n'a pas été examinée par CWG et mérite de l'être pour que le texte rejoigne l'intention. Le texte pré-voté sans être examiné était :
« The value computation and associated side-effect of the postfix-expression are sequenced before those of the expressions in the expression-list. The initializations of the declared parameters are indeterminately sequenced with no interleaving »
Hubert Tong fait remarquer que cela ne prévient pas les enchevêtrements des effets de bord, et rend des trucs comme ceci problématiques comme par le passé :
struct Y { /* ... */ };
class X {
unique_ptr<Y> p, q;
public:
X() : p { new Y }, q { new Y } {}
};
... ce qui fait partie des trucs à régler. Mike Miller précise : on ne peut pas faire tous les calculs, puis toutes les initialisation; il faut faire calcul, initialisation, calcul, initialisation, ... Jens Maurer propose une formulation pas mal, Jason Merrill propose une formulation qui met mieux en valeur cette propriété que nous recherchons :
« The postfix-expression is sequenced before each expression in the expression-list and any default argument. The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of initialization of any other parameter »
Roger Orr demande quelle sera la procédure. Mike Miller informera les gens à la plénière que nous avons retravaillé la formulation pour qu'elle porte mieux l'intention des auteurs. Jens Maurer suggère qu'on mette le « diff » sur la page des Straw Polls pour informer les gens des changements. Hubert Tong dit qu'il faudrait un numéro pour cette proposition, dans le but de faciliter le suivi des dossiers par la suite. Mike Miller s'en occupera.
Il semble que ceci soit réglé par la résolution de 1710. Mike Miller remettra 1812 à Drafting Status.
Un beau problème de sémantique ici :
« The Standard refers to capturing “entities,” and a reference is an entity. However, it is not clear what capturing a reference by reference would mean. In particular, 5.1.2 [expr.prim.lambda] paragraph 16 says,
« It is unspecified whether additional unnamed non-static data members are declared in the closure type for entities captured by reference. »
If a reference captured by reference is not represented by a member, it is hard to see how something like the following example could work:
#include <functional>
#include <iostream>
std::function<void()> make_function(int& x) {
return [&]{ std::cout << x << std::endl; };
}
int main() {
int i = 3;
auto f = make_function(i);
i = 5;
f();
}
Should this be undefined behavior or should it print 5? »
Les références sur les références sont illégales. Jens Maurer fait remarquer que dans ce cas, si on remplace « référence » par « pointeur », ça fonctionne. Jason Merrill indique que si tu modélises le tout par un pointeur sur la pile, ça va planter (car la pile de make_function() n'est plus là à l'appel de f() dans main()), alors qu'une implémentation qui utilise des membres à la pièce fonctionnerait. Certains prétendent que ça devrait être du comportement indéfini, mais je soutiens que ce serait un artéfact d'implémentation, qui serait difficile à justifier aux programmeuses et aux programmeurs. Mike Miller fait remarquer que la situation est analogue avec les λ imbriquées. On semble être d'accord : c'est défini et ça devrait fonctionner. Mike Miller va retoucher la formule en vue d'une prochaine rencontre.
Changement grammatical pour que le using d'une classe prise dans un namespace soit correctement défini. La résolution proposée semble correcte. Ready.
La formulation expliquant le moment d'instanciation de ces fonctions laisse à désirer. Richard Smith a laissé une proposition de résolution qui fonctionne, mais qui agace Hubert Tong. Ce dernier suggère d'enrichir l'exemple qui suit le texte proposé, pour clarifier le propos, et d'ajouter une note non-normative. Hubert Tong laisse entendre qu'on pourrait marquer ceci Ready car les changements sont éditoriaux, mais c'est pas clair aux yeux de tous, alors on le qualifie Drafting.
Devrait être résolu, alors Drafting.
C'est une clarification du risque d'accès concurrent dans un signal handler. Le texte proposé semble raisonnable. Jens Maurer suggère un NB Comment pour ceci et pour le cas de la proposition sur les signal handlers pré-adoptée hier.
Ça semble éditorial. Les références dans l'exemple mènent à des sections situées trop loin de l'exemple.
Ça semble aussi éditorial; on parle d'un changement de comportement entre C++ 11 et C++ 14, qu'il faut documenter à l'annexe C.
Il manque une clause pour faire de p et de this dépendants dans l'exemple suivant :
template <typename T> struct A {
void foo() {
A* p = nullptr;
bar(p); // will be found by ADL at the point of instantiation
bar(this); // same here
}
};
void bar(...);
int main() {
A<int> a;
a.foo();
}
La deuxième résolution proposée semble faire le travail. Ready.
Ceci semble éditorial. On parle d'un exemple brisé. Richard Smith l'a déjà réglé dans le texte du standard.
Gabriel Dos Reis passe nous voir. On lui explique les retouches faites à sa terminologie d'hier. Ça ne semble pas être stressant.
Mike Miller dit que ceci devrait être considéré Closed dû aux changements apportés au langage. Plusieurs pensent qu'on devrait le marquer en tant que DR sur C++ 14. Mike Miller n'est pas content car on n'aura pas de suivi officiel (une première en plus de 2500 résolutions). Mike Miller va marquer Superseded, au sens de « n'est plus applicable au WD en cours ». Ça a brassé un peu ici; on se trouve dans une procédure inhabituelle, et des gens sont très en désaccord avec l'une ou l'autre des options possibles.
C'est un gros exemple et un gros changement terminologique. J'exprime un inconfort devant ce passage :
struct X3 { auto g() { return 42; } int i = g(); // Error: in this DP-2 context, the return type of // X3::g() is a placeholder type. };
À mon avis, on a un problème ici, même si je peux comprendre que ceci soit incorrect :
struct XX { int i = g(); // Error: in this DP-2 context, the return type of // XX::g() is a placeholder type. auto g() { return 42; } };
Jens Maurer n'aime pas que nous ayons des abréviations comme DPR pour delayed-parse region. Dans le standard, nous évitons habituellement ce type de raccourci.
On peut avancer avec ce texte; ça donne des règles claires, et on peut écrire un petit quelque chose pour le truc qui m'agace ci-dessus. John Spicer se demande si on devrait d'abord passer par EWG ici. Ceux-ci me posent tous problème, en particulier X6 :
struct X5 {
static auto f() { return 42; }
auto g() -> decltype(f()) // Error: In this context, f()'s return type
// is a placeholder.
};
struct X6 {
static constexpr int f() { return 42; }
int r[f()]; // error: X6::f() is only forward-declared in this context,
// so this call is not a constant expression (5.20).
};
struct X7 {
static constexpr int f() { return 42; }
struct Y {
int r[f()]; // error: X7::f() is only forward-declared in this context.
};
};
struct X8 {
struct Y {
static constexpr int f() { return 42; }
};
int r[Y::f()]; // error: X8::Y::f() is only forward-declared in this context.
};
Je comprends qu'on cherche à résoudre un problème, mais je suis très mal à l'aise avec la solution. On verra ce qu'on peut faire avec ça ultérieurement.
On prend une pause à 10 h 15. Clark Nelson vient nous voir pour organiser la présentation des retouches terminologiques faites ce matin. Je pense qu'il craint une explosion de la part de gens qui penseraient s'être faits flouer. Je peux comprendre.
Le goûter comprend des fruits et une espèce de quiche-pizza très agréable, mais qui se mange mal avec les doigts.
Daniel Krügler vient voir Jens Maurer, qui est hors de la salle. J'en profite pour regarder avec lui comment il a écrit is_nothrow_swappable<T>. C'est simple mais propre.
Mike Miller indique que nous ferons maintenant du classement d'issues pour les placer aux divers niveaux de priorité possibles pour traitement futur.
On la laisse là pour se souvenir d'en informer Lawrence Crowl.
Priorité 0, faut changer un Shall pour un Should.
On le met en Review. Une proposition s'en vient.
Changement éditorial.
Jens Maurer pense qu'il s'agit d'un duplicat de l'issue Priorité 3. Roger Orr pense que l'autre a trait à la liste des types signés. Hubert Tong dit que le standard distingue signed integer type et signed integral type. Priorité 3.
On va passer P0348R0 en revue; on a un espace pour le faire.
Jens Maurer et John Spicer conviennent que pour Issue 1 selon l'auteur, SFINAE devrait s'appliquer sur la base du langage existant :
#include <type_traits>
struct Rational {
int num, den;
constexpr Rational(int n, int d = 1) : num(n), den(d) {}
constexpr Rational(double n) = delete;
};
template <typename T<
constexpr auto test_rational_convert(T v) -> decltype(Rational{v}, true) { return true; }
constexpr bool test_rational_convert(...) { return false; }
int main() {
static_assert(std::is_convertible<int, Rational<::value, "1");
static_assert(!std::is_convertible<double, Rational<::value, "2");
static_assert(test_rational_convert(5), "3");
static_assert(!test_rational_convert(5.0), "4");
}
Pour Issue 2, c'est un cas de Ill-formed, no change required :
#include <string>
template <typename T>
const int r = T(1) / 2; // uses division operator
template <typename T>
auto half(T&&) -> decltype(r<T>)
{ return r<T>; }
int half(const std::string&) { return 0; }
int main() {
std::string s;
half(s);
}
Pour Issue 3, la question posée est de savoir si l'instantiation d'un paramètre par défaut d'un contexte SFINAE entraîne un type dépendant. Jason Merrill se demande si c'est quelque chose de désirable. Il y a un désaccord entre les implémenteurs. Jason Merrill voit là un parallèle avec constexpr if. On envoie ça à EWG. John Spicer dit qu'il faut envoyer la demande de clarifiation de l'auteur, et la demande de changement de Jason Merrill :
template <typename T, typename U = T>
void fun(T v, U u = U()) {}
void fun(...) {}
struct X {
X(int) {} // no default ctor
};
int main() {
fun (X(1));
}
// ill-formed?
template <typename U>
void fun(U u = U());
struct X {
X(int) {}
};
Pour Issue 4, c'est implementation-dependent :
template <typename T>
struct tool_helper : T {}; // invalid if T is int
struct tool_x {
tool_x(long) {};
template <typename T,
typename U = typename tool_helper<T>::type> // T is int
tool_x(T, U = {}) {};
};
bool b = std::is_convertible<int, tool_x>::value;
// We get "hard" error when instantiating class template tool_helper which would derive from int. However, if we change the test in the last line to:
bool b = std::is_convertible<long int, tool_x>::value;
Pour Issue 5, comme pour Issue 6 :
#include <type_traits>
template <typename T> struct B : T { };
template <typename T> struct A { A& operator=(const B<T>&); };
static_assert(std::is_assignable<A<int>, int>::value, "ERR");
int main() {}
J'ai manqué des trucs car j'ai pris le relais du Wiki.
En gros, on indiquera à l'auteur qu'il a raison sur deux points et que ce sont des bogues à corriger sur son compilateur de prédilection.
Ceci est ambigü :
template<class T>
void print(ostream &os, const T &t) {
os << t;
}
template <class T, class... Args>
void print(ostream &os, const T &t, const Args&... rest) {
os << t << ", ";
print(os, rest...);
}
int main() {
print(cout, 42);
print(cout, 42, 1.23);
}
On n'est pas convaincus de pouvoir aider ici.
Roger Orr dit qu'on en a parlé à Kona, mais que les gens n'étaient pas satisfaits de la résolution. C'est basé sur un comportement complètement dément :
void *operator new(size_t n, std::string s) {
std::string t = std::move(s);
std::cout << "new " << t << std::endl;
return operator new(n);
}
void operator delete(void*, std::string s) {
std::cout << "delete " << s << std::endl;
}
struct X { X() { throw 0; } };
int main() {
try {
new ("longer than the small string buffer") X();
} catch (...) {}
}
On va laisser ça implementation-defined, pour que quelqu'un qui souhaite supporter ce genre de truc un peu atroce puisse le faire en introduisant une temporaire silencieuse, et pour que le comportement remarqué (avoir une string vide dans operator delete) demeure légal.
On prend la pause pour le dîner vers 12 h 2. Ce fut un matin quand même productif. Les issues de CWG sont des exemples de code extrêmements vils et malsains; j'ai toujours un plaisir pervers à les absorber et à me demander quel esprit tordu a pu les pondre.
Cet après-midi, nous avons la plénière classique, puis une séance de travail courte avec CWG. Par la suite, puisque c'est mon anniversaire de mariage, je vais aller rejoindre mon amoureuse et profiter de sa charmante compagnie.
Les votes du samedi son typiquement très légers et très rapides, le travail de terrain un peu plus rude étant résolu la veille. Pour aujourd'hui, le fait que nous ayons dû changer une ou deux phrases en début de journée va peut-être prolonger les débats quelque peu.
L'exemple charmant de Thomas Köppe est exposé, pour montrer ce qu'on a fait de bien cette semaine. avec C++ 14 (j'ai ajusté la version initialement écrite ici, que j'avais transposée de mémoire, puisque Herb Sutter, dans son journal de voyage, a publié une version corrigée de l'exemple initial) :
unordered_map<string, unique_ptrÉ<Foo>> items;
vector<unique_ptr<Foo>> standby;
//
// Desired semantics of f: If there is currently no item 'id', install
// 'foo' as item 'id'. Otherwise, put 'foo' on the standby list for later.
//------------------------------------------------
// Before C++17: 7 lines + 4 pitfalls
//
void f(string id, unique_ptr<Foo> foo) {
auto it = items.find(id);
if (it == items.end()) {
auto p = items.emplace(move(id), move(foo));
p.first->second->launch();
} else {
standby.push_back(move(foo));
standby.back()->wait_for_notification();
}
// Notes:
// * Variable 'id' can no longer be used (moved-from); or...
// * ...would need to pass by 'const string& id' and force copying.
// * Map lookup performed twice. Ordered map could use lower_bound +
// hint, but unordered map cannot.
// * (Cannot emplace unconditionally, because it might destroy *foo.)
}
... et avec C++ 17, c'est plus direct, plus simple et plus rapide :
unordered_map<string, unique_ptr<Foo>> items;
vector<unique_ptr<Foo>> standby;
// Desired semantics of f: If there is currently no item 'id', install
// 'foo' as item 'id'. Otherwise, put 'foo' on the standby list for later.
//------------------------------------------------
// With C++17: 4 lines + none of those pitfalls
//
void f(string_view id, unique_ptr<Foo> foo) {
if (auto [pos, inserted] = items.try_emplace(id, move(foo)); inserted){
pos->second->launch();
} else {
standby.emplace_back(move(foo))->wait_for_notification();
}
}
Clark Nelson demande s'il y a eu des nouveautés depuis hier. Mike Miller se présente pour expliquer la retouche terminologique du matin, et le fait avec brio. La nouvelle terminologie est présentée en tant que suggestion à l'auditeur. Gabriel Dos Reis, l'auteur de la proposition originale, l'a vue et est à l'aise. Ça ne semble pas causer de froid.
Clark Nelson indique qu'il faut voter les minutes de Jacksonville. C'est fait.
Hans Boehm demande s'il y a un nouveau Parallelism TS. Oui, mais on n'a pas à l'approuver aujourd'hui car il n'y a pas eu d'ajouts cette semaine.
Une question sur ce qu'on peut voter sur les modifications au Parallelism TS ou non est discutée entre Herb Sutter et Pablo Halpern. Jeffrey Yasskin dit que pour le moment, on ne peut rien baser sur C++ 17 dans les TS, mais ça changera à partir du DIS.
Marshall Clow fait un sondage plus formel sur les deux premières semaines d'août pour une séance spéciale de LWG à Chicago.
Pour les prochaines rencontres :
Quelqu'un mentionne qu'on aura trois rencontres hors-Europe consécutives, mais en 2018 ça ressemble à Rapperswil (Suisse), et en 2019 on pense aller en Europe deux fois.
John Spicer annonce les prochains mailings, mais j'ai pas pris les dates en note.
Walter E. Brown fait une motion de remerciement de nos organisateurs et de nos hôtes, plein de gens. Herb Sutter dit que ça s'est déroulé très rondement et qu'on envisage revenir ici dans le futur. Ville Voutilainen dit que pour ce qui est du prospect de tenir une rencontre d'hiver ici, il est contre, et c'est une position nationale (on se bidonne). Le vote d'hier n'a pas d'opposition, et est officiel : nous avons un DIS pour C++ 17, et il nous rend heureux.
On se déplace vers la sale de CWG. Il est 14 h 15.
On aborde les papiers que l'on a le temps d'aborder.
Les exemples motivant ce travail sont tous horribles :
struct A {
A() { puts("ctor"); }
A(const A&) { puts("copy"); }
const A&get() const { return *this; }
~A() { puts("dtor"); }
};
struct B { B(A, A) {} };
typedef A A2[2];
A2 a = { A().get(), A().get() };
B b = { A().get(), A().get() };
int c = (A2{ A().get(), A().get() }, 0);
int d = (B{ A().get(), A().get() }, 0);
int main() {}
// ... ou encore ...
int i = i++;
int j = j;
// ... ou encore ...
const int& f(const int& x) { return x; }
int y = f(5);
Les initialisations avec accolades peuvent apparaître un peu partout, mais ce qui définit une expression complète (full-expression) est mal décrit par le standard. La formulation de Jens Maurer cherche à régler ce problème. Par exemple, avec ceci :
struct A { int x; };
struct B { int y; struct A a; };
B b = { 5, { 1+1 } };
...les constituent-expressions de l'initializer utilisé pour b sont 5 et 1+1. Les exemples du correctif proposé incluent :
struct S {
S(int i): I(i) { } // full-expression is initialization of I
int& v() { return I; }
~S() noexcept(false) { }
private:
int I;
};
S s1(1); // full-expression is call of S::S(int)
void f() {
S s2 = 2; // full-expression includes call of S::S(const S&)
if (S(3).v()) // full-expression includes lvalue-to-rvalue and
// int to bool conversions, performed before
// temporary is deleted at end of full-expression
{ }
bool b = noexcept(S()); // exception specification of destructor of S considered for noexcept
} // full-expression is destruction of s2
struct B {
B(S = S(0));
};
B b[2] = { B(), B() }; // full-expression is the entire initialization, including the destruction of the temporaries
Daveed Vandevoorde nous informe qu'EWG essaie de donner une vie plus... riche aux expressions entre accolades. Ce sera une petite fête d'intégrer les deux approches ensemble.
On essaie de voir comment intégrer expression, initialisation et listes de valeur dans un tout grammatical harmonieux. La grammaire ne sied pas nécessairement à cette vision (par ailleurs fort raisonnable) pour le moment. Jens Maurer explique l'intention; Jasom Merrill pense qu'on doit aussi tenir compte des conversions. Jason Merrill place une braced-init-list dans le contexte d'une full-expression même si elle n'en est pas une elle-même. Fedor Sergeev suggère qu'on ajoute un enrichissement pour rendre full-expression plus... englobant.
Jens Maurer mentionne que la définition doit tenir compte des références, qui peuvent apparaître et doivent avoir été initialisées au préalable.
Alisdair Meredith met de l'avant les Fold Expressions. Il a l'impression que ça passe, mais veut confirmer. Jason Merrill pense que ça passe le test, parce que les volets grammaticaux discutés dans cette section apparaissent après l'expansion des expression variadiques.
Alisdair Meredith met de l'avant les répétitives for sur des intervalles, mais il semble que la réécriture a lieu avant de frapper ce stade.
Patrice Roy blague à
l'effet qu'il semble y avoir une règle « standardaise » à l'effet que tout
exemple utilisé ici ne passerait pas une revue de code. Roger Orr
rétorque qu'on a pensé laisser traîner une note indiquant « If you see
any such code excerpt in the wild, please bring it back to the nearest
standards committee » .
On marque celle-ci Tentatively Ready, parce que la rencontre actuelle n'est pas une rencontre officielle (ce serait Ready sinon).
L'idée est que memcpy() sur des volatile ne fait pas la bonne chose, et que ce changement visait à régler ce vilain problème.
Il semble que les membres volatile dans les classes triviales brisent les ABI des compilateurs. Alisdair Meredith demande s'il serait possible de faire le changement quand on sera disposés à briser l'ABI de toute manière, mais Jason Merrill indique que c'est l'ABI avec C que ça brise. Jens Maurer souhaite une proposition qui ferait le tour du problème de volatile pour pour clarifier le propos. Hubert Tong dit que les fonctions *_s() de C posent problème pour cette raison.
On marque celle-ci Tentatively Ready. Nous avons posé un geste qui a mené un Breaking Change et il faut reculer. Alisdair Meredith demande si nous sommes prêts à marquer volatile comme déprécié, mais nous n'en sommes pas là.
On parle d'un correctif somme toute simple du texte du standard, qui laisse entendre que prendre l'adresse d'un attribut de classe (static data member) ne serait pas value-dependent. Roger Orr se demande s'il y a duplication avec le concept d'address-dependent. La solution semble passer par un raffinement de la définition de templated entity.
Jason Merrill suggère de restreindre la définition au current instantiation, estimant que si ça va plus loin que l'instanciation en cours, ce devrait être type-dependent, mais John Spicer pense à un cas qui m'a échappé et qui nous fait reculer.
Beau travail, Tentatively Ready.
On ferme les livres vers 15 h 20. Grosse semaine!
Retour à la chambre. Za et Cindy vont faire du vélo (il a plu une partie de la journée, mais il y a maintenant une accalmie). Je me sers un scotch, je prends mes courriels, je diffuse un peu la bonne nouvelle à propos des décisions qui ont été prises ici.
Je dois avouer que je regarde le langage que nous avons réussi à concocter et que c'est plutôt encourageant, mieux que ce que j'aurais pu croire en sortant de Kona, où le fait que de gros morceaux espérés depuis longtemps, comme les concepts, les coroutines et les modules, amenait un peu de tristesse chez nous tous, qui souhaitions une mise à jour importante du langage. Finalement, nous avons plusieurs ajouts qui vont aider tout le monde, rapidement, à écrire de meilleurs programmes, plus élégants, plus simples et plus rapides. Je pense que nous sommes nombreux ici à sourire en ce moment.
J'ai travaillé un peu sur mon doctorat pour me remettre dedans. Va falloir donner un coup de ce côté au retour.
Au retour de Za et Cindy, Za fait une brève sieste, puis nous allons prendre une marche pour aller souper dans un restaurant français (à la sauce finlandaise). Nous l'avions croisés plus tôt dans la semaine, et mes compagnes de voyage avaient vérifié plus tôt dans la journée (c'est fête, et il y a peu d'endroits en ville qui ne sont pas fermés). Puisque c'est notre anniversaire de mariage aujourd'hui, Za et moi souhaitions aller prendre un repas un peu plus sophistiqué ce soir; Za ne se sent pas bien depuis deux jours alors c'est une soirée tranquille, mais nous voulons quand même souper.
Idées en rafale :
Demain, on « chill » et on essaie de voir si on peut aller faire du kayak sur la rivière non loin d'ici.
Premier (et seul!) matin à se lever sans réveil. C'est fête encore ici alors il y a peu à faire outre prendre le temps.
Quand Za et Cindy se réveillent, nous prenons une petite marche dans les environs. Café, viennoiserie, puis un tour dans le parc qui chevauche les îles du coin, avec un petit tour dans une tour fortifiée transformée en café pour profiter de la vue tout en haut. Marche en ville, crème glacée (excellente; ici, il y a autant des commerces qui vendent de la crème glacée presque à chaque coin de rue; Za a pris une crème glacée molle aux poires, et moi deux boules respectivement au nougat + caramel et la lime + mascarpone). Petit tout à la place, Cindy fait des châteaux de sable atypiques, je me trempe les pieds. Petite marche encore, un peu hors des sentiers. Retour ensuite à la chambre pour un peu de repos et pour contacter les enfants (Ludo, en fait, car Vayda dormait encore et les autres sont éparpillées ici et là, dû à la vie qui suit son cours... On vous aime!).
En soirée, Za et Cindy sont allées à la plage (une plage plus loin, près d'un autre hôtel, et vraiment fantastique). Elles m'ont contacté pour que je leur apporte leurs maillots, mais je me suis perdu en chemin. Pas vraiment grave, si ce n'était des moustiques très voraces sur la route. Je suis arrivé trop tard à la plage, elles étaient reparties (il faisait encore beaucoup soleil à 21 h 30, ne vous en faites pas), mais j'ai pu me mettre les pieds à l'eau, et elle était formidable en effet. Le trajet du retour, une fois la route apprivoisée, fut beaucoup plus court que celui pour m'y rendre; après avoir vu cette plage, notez que si le comité revient à Oulu dans le futur (et c'est bien possible, car l'accueil fut excellent et que ce type de climat et d'ensoleillement favorise la productivité), j'apporterai un maillot.
Au retour à l'hôtel, j'avais très soif, et la bière fut excellente.
Debout vers 5 h, 6 h 15 pour mes compagnes de voyage. On paquete les derniers trucs et on fait le check-out. Un taxi arrive dans les deux minutes qui suivent et nous sommes à l'aéroport environ 1 h 30 avant le départ. Ici, petit aéroport et tout, ça suffit.
Excellent service, déjeuner un peu dispendieux (mais bon, honnêtement), belles accomodations (c'est très confortable, très design, le WiFi est gratuit et de bonne qualité). Nous relaxons un peu en attendant l'embarquement. J'apprends par courriel que ma proposition de présentation pour CppCon 2016 a été acceptée (chic!) alors je vais pouvoir voyager à prix raisonnable en septembre. C'est important car mes sources de financement pour les déplacements sont moins riches que par le passé (les fonds disponibles sont beaucoup moins grands qu'avant chez mes employeurs).
L'aéroport Heathrow de Londres est immense. C'est déstabilisant d'être en autobus et de voir les véhicules venir en sens contraire et passer à droite de nous. Les boutiques sont démesurément chères, cela dit; c'est un lieu de transit pour gens extrêmement riches.
Montréal nous accueille dans le bonheur, comme toujours, vers 20 h 20. C'est British Airways qui nous a amenés de Londres à Montréal, avec un excellent service, à la fois souriant et efficace, de bons repas, mais si vous voyagez avec eux, préférez nettement le thé au café. Voilà, c'est dit.
Gros merci à mon chic papa Réal pour nous avoir cueillis à notre arrivée et nous avoir ramenés vers nos domiciles respectifs. Ma grande Marguerite était chez moi à mon arrivée, et ce fut le temps d'examiner les changements de situation (une chatte avait accouché; il fallait faire les litières, chose normale du fait que nous avons plusieurs chats; la cage des oiseaux avait été bousculée; fallait remettre de l'eau dans la piscine, car il a fait très chaud en notre absence; fallait prendre une bonne douche, évidemment; la tondeuse est brisée; etc.). Demain matin, c'est le retour des enfants, des chiens et du train-train quotidien...
Trucs que je retiens de la journée :
Trucs à retenir, d'ordre plus général :
À faire la prochaine fois, avant de me présenter à la rencontre :