À propos de WG21, Croydon 2026 (mars)

Je participe à cette rencontre à distance encore une fois (ces dernières années je n'ai pas réussi à mettre de côté les fonds requis pour aller à ces rencontres en personne, malheureusement). La rencontre de cette semaine se tenant à Croydon (Londres, Angleterre), le décalage horaire sera mais j'ai vu pire. J'aurais normalement eu des dossiers à défendre mais j'ai été très malade en février et je n'ai pas réussi à accorder à mes dossiers le suivi dont ils auraient eu besoin, alors ça ira à cet été pour moi. De toute manière, cette semaine, le centre d'attention est C++ 26 et mes dossiers visent C++ 29.

Certains dossiers chauds à propos de la réflexivité statique demanderont des efforts, et les contrats demeurent controversés (c'est le dossier le plus controversé depuis des années; j'aimerais bien qu'ils deviennent officiellement partie du langage pour que nous puissions les mettre vraiment à l'essai et mieux comprendre comment bien les utiliser). Je devrais passer ma semaine chez CWG comme à mon habitude.

Ce sera la première prestation de Guy Davidson à titre de Convener. La structure administrative du comité change, ce qui est normal dans les circonstances. Une modernisation notoire est que nous passons d'un Wiki commun où nous partagions tous et toutes une même identité (oui, je sais!) à un Wiki où nous sommes identifiés individuellement et où nos avons des privilèges en conséquence. C'est une bonne idée.

Tout ce qui suit est anonymisé et simplifié, dans le respect du code de conduite d'ISO en vigueur lors de nos rencontres.

Ce document est incomplet (j'ai manqué de temps). Je compléterai dès que possible.

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

Jour 0 – 23 mars 2026

C'est un drôle d'horaire cette semaine car le changement d'heure a eu lieu au Québec mais il se produira en Europe à la fin de la semaine. C'est moins violent pour moi (on commence à 4 h 30 heure de Montréal plutôt que 3 h 30 comme ce serait normalement le cas).

Nina Ranns fait l'accueil, puis passe le micro à Guy Davidson. Guy Davidson mentionne la présence de 27 pays cette semaine. Entre autres, on a la Russie et l'Ukraine, les États-Unis et la Chine... Beaucoup de monde! Phil Nash est notre hôte et nous dit quelques mots.

Nina Ranns présente le code de conduite, et les règles lors des votes. Le nouveau système de Wiki mène à des applaudissements bien mérités. On laisse les nouveaux membres et les invité(e)s se présenter. Pour une première fois, à ma connaissance, quelqu'un se présente comme un « producteur de contenu »; on a aussi quelques personnes de Rust qui est présent pour aider à l'interopérabilité entre nos deux langages, incluant la personne qui gère wg21.link ce qui est doublement chouette! On a aussi une représentante de Apple qui vient pour discuter d'interopérabilité avec Swift.

On présente l'organisation de la semaine et la répartition des groupes d'études comme des groupes de travail dans les diverses salles. Il semble qu'il y aura une alerte d'incendie dans le courant de la semaine (c'est gentil de nous prévenir). Il y aura quatre séances de soirée cette semaine, sur des thèmes intéressants d'ailleurs.

Le gros morceau de la semaine est le traitement des NB Comments de C++26. Le dossier le plus chaud est probablement celui des contrats, acceptés à la plus récente rencontre mais auxquels il y a encore de l'opposition (et de l'exaspération, il faut le dire).

Nina Ranns fait un rappel de l'importance de se comporter de manière humaine. Elle est vraiment excellente à cela.

La plénière se termine et les gens se déplacent vers les salles où se tiendront les travaux qui les touchent le plus. Pour moi, ce sera CWG comme à l'habitude.


(j'ai été ralenti par des ennuis de connectivité alors j'ai manqué le début de la rencontre; on fait le tri des NB Comments à traiter quand je parviens à rejoindre le groupe)

P3924 – Fix inappropriate font choices for "declaration"

On a deux polices de caractères trop semblables pour deux familles de termes distinctes du standard, et ça a provoqué des erreurs récemment. On vise à corriger cela.

On fait le tour des sections affectées. Tout semble Ok. Davis Herring se questionne sur l'intérêt d'avoir autant de variantes de « déclarateur » dans le texte et propose une approche alternative, mais je ne pense pas qu'on va faire ça cette semaine.

Avec des changements très mineurs, on soumettra ceci pour vote samedi.

Core Issue 2228. Ambiguity resolution for cast to function type

Ceci est (étrangement) ambigu :

int x = (int()) + 5;

Ceci est dû à une ambiguïté (est-ce une signature de fonction ou est-ce un int par défaut?). On a d'autres cas :

struct T { int operator++(int); T operator[](int); };
int a = (T()[3])++; // not a cast

(S())[]->A<int>;              // OK, constructor call
(S())[]->A<int> {return {};}; // error: C-style cast of lambda

On examine la proposition de changement à la grammaire pour résoudre le tout (ça introduit un terme grammatical amusant : nofun). Ça change un exemple :

template <class T> struct X {};
template <int N> struct Y {};
X<int()> a;   // type-id
X<int(1)> b;  // expression (ill-formed)
Y<int()> c;   // type-id (ill-formed)
Y<int(1)> d;  // expression
void foo(signed char a) {
  sizeof(int());    // type-id (ill-formed) expression
  sizeof(int(a));   // expression
  sizeof(int(unsigned(a)));    // type-id (ill-formed) expression
  (int())+1;              // type-id (ill-formed) expression
  (int(a))+1;             // expression
  (int(unsigned(a)))+1;   // type-id (ill-formed) expression
}
typedef struct B { int C[2]; } *B, C;
void g() {
sizeof(B()->C[1]);     // OK, sizeof(expression)
sizeof(auto()->C[1]);  // error: sizeof of a function returning an array
}

On examine la grammaire résultante et certaines pensent que ça brise les déclarations de fonctions avec trailing return types. On travaille un peu et on arrive à résoudre cette préoccupation. Ça nous prend le reste de l'avant-midi. On penche pour Tentatively Ready mais c'est un changement compliqué alors on hésite. John Spicer suggère de viser C++29 mais d'en faire un DR, pour se donner le temps de réfléchir.

(je dois ensuite quitter pour la journée car j'ai un rendez-vous médical de routine puis j'enseigne).

Jour 1 – 24 mars 2026

Je me lève vers 3 h du matin pour lire ce qui s'est passé hier après-midi. Un gros dossier est celui des valeurs consteval ou des types consteval : on a présentement des types consteval-only, utiles entre autres pour la réflexivité, mais une approche concurrente qui semble prometteuse est celle de valeurs consteval-only. On peut voir des avantages à cette nouvelle approche, mais il est très tard dans le cycle de C++26 pour un tel changement et il y a des tenants des deux approches.

C'est merveilleux que nous ayons des scribes pour ces rencontres. Ça permet de suivre les débats.

La rencontre débute et Jens Maurer nous explique que nous devrons nous joindre à EWG plus tard aujourd'hui pour porter la parole de CWG sur cet important sujet. On attire aussi notre attention sur Core Issue 2675 qui avait une formulation interférant avec du texte chez LWG. Une reformulation est proposée.

Core Issue 2765. Address comparisons between potentially non-unique objects during constant evaluation

On n'est pas clairs sur nos intentions quant à des cas comme ceci :

constexpr bool b = "abc" == "abc";

Ce qui est sur la table est :

constexpr const char *f() { return "foo"; }

constexpr bool b1 = "foo" == "foo";   // error: non-constant
constexpr bool b2 = f() == f();       // error: non-constant
constexpr const char *p = f();
constexpr bool b3 = p == p;           // OK, value of b3 is true
constexpr bool b4 = "xfoo" + 1 == "foo\0y"; // error: non-constant; string literal object could contain "xfoo\0y"
constexpr bool b5 = "foo" == "bar";   // OK, value of b5 is false
constexpr bool b6 = "foo" == "oo";    // OK, value of b6 is false; offsets would be different in a merged string literal object
extern int i;
constexpr std::initialized_list<int*> il1{ &i };
constexpr std::initialized_list<int*> il2{ &i };
constexpr std::initialized_list<int*> il3{ (int*)nullptr };
constexpr bool b7 = *il1.begin() == *il2.begin();
constexpr bool b8 = il1.begin() == il3.begin(); // error: non-constant

Ça mène à l'étrange idée d'un type de constexpr-unknown representation pour des trucs comme les pointeurs, les union et les objets volatiles, et de potentially non-unique object pour les trucs comme les pointeurs dans un littéral texte.

On travaille sur l'exemple car on veut clarifier les diverses facettes de la règle proposée. Hubert Tong propose ceci :

#include <initializer_list>
extern int i;
constexpr std::initializer_list<int *> il1{ &i };
constexpr std::initializer_list<unsigned long> il2{ 0 };
static_assert(il1.begin() == (void *)il2.begin()); // ill-formed

Après une bonne heure de teavail, on arrive à un niveau de satisfaction acceptable. On amènera ça pour vote samedi.

Core Issue 3123. Global lookup for begin and end for expansion statements

L'enjeu est que nous avons une définition de expansion-iterable qui, sous sa forme actuelle, peut provoquer des instanciations de templates et ralentir la compilation. Une proposition a été soumise sous la forme de P4026 et cette proposition fut acceptée par EWG.

P4136 – #line is not in line with existing implementation

On a un enjeu ici parce qu'il est possible de mettre #line 2147483648 qui dépasse la valeur maximale d'un entier signé sur 32 bits et que ceci mène à du comportement indéfini. La proposition est de rendre ceci conditionally supported, mais quand on dit ça il faut indiquer ce qu'on fait quand ce n'est pas supporté.

Core Issue 3103. Corresponding members and by-value object parameters

On a le problème que ceci est ill-formed:

struct K {
  void f(this K);
  void f();
};

... alors que ceci, essentiellement équivalent, ne l'est pas :

struct OK {
  void f(this OK);
  void f() &;
};

La nuance est dans la définition de « correspond » dans le texte du standard. P4138 couvre en détail l'interaction de correspond avec les ref-qualifiers de fonctions membres. On examine ce qui y est décrit. On passe le reste de la première partie de la journée à examiner l'approche mise de l'avant par cette proposition.

(brève pause matinale)

Après la pause, on discute de la proposition et on pense que EWG devrait la regarder. La proposition rejoint la vision de CWG et nous sommes disposés à travailler sur le Wording qu'elle comporte, mais on souhaite l'avis de EWG avant de procéder.

P4136 – #line is not in line with existing implementation

L'auteur est parmi nous maintenant. On blague parce que le Wording n'est vraiment pas terrible, mais l'essentiel est préexistant et n'est pas de sa faute (ses correctifs sont pertinents et tout petits). La proposition sera portée au vote samedi.

(je dois m'absenter une heure environ car Ludo, mon plus jeune, a manqué son autobus; je reviens tout juste avant la fin de l'avant-midi à Croydon et on discute de P3865)

P3865 – Class template argument deduction (CTAD) for type template template parameters

Je n'ai pas le contexte mais on débat de la validité de certains exemples. C'est un sujet très abstrait. L'exemple suivant semble provoquer des réactions :

template <typename ... Ts>
  struct Y {
    Y();
    Y(Ts ...);
  };
template <template<typename T = char> class X>
  void f() {
    X x0{}; // OK, deduces Y<char>
    X x1{1}; // OK, deduces Y<int>
    X x2{1, 2}; // error: cannot deduce X<T> from Y<int, int>
  };
template void f<Y>();

On en reparlera. C'est l'heure du dîner, et l'après-midi reprendra chez EWG (j'espère être de retour à temps; mon amoureuse Za et moi avons une vaccination de chien à faire pendant le « dîner » londonien).

(à mon retour du vaccin de notre chien Pauline, Barry Revzin explique P4101 qui décrit le modèle consteval-only values chez EWG et les membres de CWG sont présents)

Les débats autour du modèle consteval-only values en comparaison avec le modèle consteval-only types sont costauds. Un enjeu est que nous devons faire un choix car sinon, les implémentations planteront devant les cas d'utilisation proposés. Dan Katz fait remarquer que la spécification existante exige dans certains cas que le compilateur soit un oracle tout puissant (par exemple la réflexivité sur un pointeur extern). Certains cas de méthodes virtuelles consteval sont possibles seulement dans un monde d'évaluation consteval ce qui peut causer des dégâts si le monde compile-time se met à fuir dans le monde run-time. Il soulève aussi la question de l'identité d'une reflection, par exemple dans le cas où on comparerait une version run-time et une version compile-time d'une « même » reflection.

Ensuite, Wyatt Childers présente P4135 qui décrit les mérites du modèle consteval-only types. Il commence par dire que le modèle consteval-only values est intéressant mais si dit d'avis qu'on réagit trop fort selon lui. Il parle de son expérience en métaprogrammation et dit avoir étudié sous Andrew Sutton. Avec quelques exemples, il met de l'avant son intérêt pour permettre de réaliser des solutions simples aux problèmes qu'il rencontre et montre des cas qui devraient fonctionner mais ne le font pas. Ses exemples profitent du fait (par exemple) qu'un type holder<T> pour une type T qui soit consteval-only devient implicitement consteval-only ce qui peut mener à de meilleurs diagnostics et à moins de bruit dans le code source. Il montre qu'il a implémenté son approche en deux jours sur le compilateur d'EDG et qu'il obtient des diagnostics de qualité. Une partie forte de son argumentaire est que sa proposition repose sur le statu quo et que C++26 se termine cette semaine.

Les séances de questions / réponses des deux propositions sont intéressantes. On est en terrain extrêmement novateur et les cas limites se cachent dans les ombres. Shafik Yaghmour signale qu'en tant qu'implémenteur, l'approche consteval-only values lui semble plus facile à comprendre et à implémenter, mais à son avis clang n'est pas encore proche d'implémenter le tout alors il ne voit pas l'urgence de prendre un vote. D'autres passent au micro et disent aussi avoir un faible pour l'approche consteval-only values mais préférer ne pas trancher aujourd'hui.

John Spicer rappelle qu'on parle d'une décision très importante et défend l'idée de prendre son temps. Il ne se dit pas d'avis qu'il faille se presser dans ce cas. Il dit être arrivé à la conclusion que nous aurons éventuellement des consteval-only types et pense qu'il faudrait réfléchir à la possibilité d'avoir un jour les consteval-only values aussi.

Corentin Jabot défend l'idée que laisser des std::meta::info glisser vers le monde run-time ne cause pas de dégâts. Tout ce qu'on peut faire avec cela, c'est les comparer. Il se dit aussi plus confiant en sa capacité d'implémenter le modèle consteval-only values avec clang. Il signale qu'un enjeu avec le design consteval-only types est que le fait qu'un type soit consteval-only ou pas dépend du moment où ce type est observé.

(brève pause du milieu de l'après-midi)

On signale que présenter ces options devant SG20 pour discuter de l'aisance d'enseignement serait pertinent, ce qui ajouterait à l'intérêt de prendre son temps.

Gabriel Dos Reis pense que dans un cas comme dans l'autre, ces bug fixes cachent des nouveaux features. Il dit que la spécification actuelle de immediate escalation est en partie incohérente et n'est vraiment pas simple à implémenter. Selon lui, mieux vaut ne pas trancher aujourd'hui.

Daveed Vandevoorde, pour sa part, dit qu'en tant qu'implémenteur il souhaite qu'une décision soit prise par EWG. Il préfère le modèle consteval-only values mais la priorité pour lui est de savoir quoi faire. Barry Revzin se dit d'avis quele modèle consteval-only values couvre tous les cas que le modèle consteval-only types couvrirait, en plus de quelques cas que nous devrons couvrir de toute manière. Hubert Tong rappelle que le regard de CWG ne s'est posé sur l'approche consteval-only values qu'hier, pas avant; à son avis, le leakage n'est pas la clé ici mais ce qui compte vraiment est de s'assurer qu'un appel de fonction immédiate le demeure, et explique que c'est avec le modèle consteval-only types qu'on a cette certitude le plus directement.

(je ne prends pas toutes les interventions car il y en a vraiment beaucoup)

Jakub Jelinek se dit d'avis que si on conserve le statu quo, on aura le modèle consteval-only types et que cela sera difficile à changer par la suite. Herb Sutter rejoint Gabriel Dos Reis et John Spicer et préfère attendre. Corentin Jabot mentionne qu'à court terme, seul gcc aura la réflexivité alors le plus important est de savoir ce que sera l'effet de nos décisions sur ce compilateur. Jason Merrill signale que peu importe la décision, la réflexivité sera expérimentale alors on pourra faire des changements. (on a des gens qui vont jusqu'à se questionner si la réflexivité est prête à faire son entrée officiellement, mais ça m'étonnerait qu'on aille jusque là; John Spicer fait d'ailleurs un rappel qu'on parle de cas limites ici, et que ça ne devrait pas disqualifier l'ensemble de l'oeuvre)

On vote sur l'idée de trancher cette semaine, et il n'y a pas de consensus. On garde donc le statu quo pour le moment sur ce plan. On prend ensuite un vote d'encouragement pour l'une ou l'autre des deux approches, question d'aider les implémenteurs à s'orienter, et l'approche consteval-only values semble plus populaire pour le moment mais on verra pour le futur.

(CWG quitte la pièce; quand la discussion reprend chez CWG, on discute des contrats qui semblent ne pas avoir été modifiés et être en route vers C++26)

P2285 – Are default arguments part of the immediate context?

Il semble que EWG ait décidé que non, alors notre travail est d'attendre une version mise à jour de la proposition et tenant compte de ce choix directionnel. Brian Bi ne semble pas convaincu que EWG ait compris qu'on avait aussi besoin d'une décision sur les valeurs par défaut des valeurs par défaut des variables membres d'un agrégat. (note plus tard dans l'après-midi : ça semble être le cas)

Core Issue 3150. Incomplete consteval-only class types

Jens Maurer suggère qu'on attende que EWG prenne une décisions avant de faire quoi que ce soit ici.

Core Issue 3162. Evaluation context of manifestly constant-evaluated expressions

Ce qui suit retourne 1 dû au moment où l'instantiation du type survient, mais ce n'était pas l'intention :

struct S;
consteval size_t f() {
  constexpr bool b = is_complete_type(^^S);
  return b ? 1 : 2;
}

struct T;
consteval {
  define_aggregate(^^S, {});
  define_aggregate(^^T, {
    data_member_spec(^^int, {.name="m", .bit_width=f()}),
 });
}

int main() {
  return bit_size_of(^^T::m);
}

Le changement proposé est principalement un déplacement de passages du standard pour faire en sorte que l'ordre dans lequel les règles sont appliquées rejoignent mieux l'idée initiale. On penche pour marquer le tout Tentatively Ready pour le moment puis on lit le texte avec attention. C'est délicat parce que déterminer le point d'instanciation d'un type détermine ce qu'on peut faire par réflexivité avec ce type (on fait une note non-normative pour préciser cela).

Dan Katz va travailler là-dessus ce soir pour qu'on puisse le travailler demain.

Jour 2 – 25 mars 2026

On reprend les travaux vers 4 h 30 heure de Montréal. Les discussions sur les modèles consteval de la veille sont encore actives dans la salle.

Core Issue 3158. Constification for splice-expressions

Jens Maurer explique que ceci lui semblait évolutionnaire, donc il l'a envoyé à EWG qui a indiqué que ceci n'était pas une défectuosité : le comportement obtenu est volontaire et délibéré. Certains sont en désaccord alors il se peut que ce soit rediscuté aujourd'hui.

3162. Evaluation context of manifestly constant-evaluated expressions

Il y a eu des changements depuis hier car le texte menait à une récurrence infinie.

On a cet exemple qui teste la complétion d'un type:

consteval int f(int p) {
  struct S;
  constexpr int r = /* P */ std::meta::is_complete_type(^^S) ? 1 : 2;
  consteval {
    std::meta::define_aggregate(^^S, {});
  }
  return (p == 0) ? f(p - 1) : r;
}
static_assert(f(1) == 2);

On essaie de comprendre ce que l'exemple cherche à démontrer (est-ce que le type est toujours incomplet quoi qu'il advienne?). On examine la proposition de correctif « anti récurrence infinie » pendant un certain temps (ça donne lieu à une bonne blague quand Jens Maurer dit « you can keep staring and tell me when you're done » et Jason Merrill réplique, en parlant lentement, « I think it's staring back at me... » (un moment Nietzschéen parfait!).

On remarque que le texte suppose un ordre entre certaines opérations internes de l'acte de compiler, d'une manière pour laquelle le reste du standard ne prend pas position. C'est peut-être une bonne chose de clarifier cet aspect. On en discute un peu (l'avènement de la réflexivité statique nous force à examiner notre propre mécanique de plus près car elle révèle, par sa nature-même, des aspects du processus de compilation qui étaient invisibles auparavant).

On va retravailler là-dessus cet après-midi en la présence Dan Katz pour nous assurer que nous avons bien compris son intention.

On passe un peu de temps à regarder les NB Comments qu'on pourrait traiter cette semaine, et à placer certains d'entre aux à l'agenda cette semaine (si on ne les traite pas, ils ne seront pas dans C++26).

P4004 – Reconsider CWG 1395 "Partial ordering of variadic templates reconsidered"

On a un problème avec des cas comme celui-ci :

template<typename ... T> char *f(T &...); // #1
template<typename T> int *f(T &&); // #2
int i;
auto *p = f(i);

On veut que #2 soit choisi, mais les règles disent #1 ce qui est nuisible. On a des divergences d'implémentation. En gros, c'est un changement qui brise trop de code.

Les changements terminologiques consistent pour l'essentiel à un retour au statu quo pré-CWG 1395 pour la moitié du texte. On a aussi un problème avec des cas comme :

template<class... Args> void f(Args... args); // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2> void f(T1 a1, T2 a2); // #3
f(); // calls #1
f(1, 2, 3); // calls #2
f(1, 2); // calls #3; non-variadic template #3 is more specialized
// than the variadic templates #1 and #2

... car le texte ne nous aiguille pas correctement vers la bonne fonction dans certains cas.

On prend un bon moment à regarder les règles proposées pour voir si elles nous mènent là où on souhaite aller. Ça semble être le cas. Génial! On en fera un DR et ce sera amené pour vote samedi.

P3865 – Class template argument deduction (CTAD) for type template template parameters

Ce que cette proposition vise à permettre est ceci :

template<typename ... T>
  struct C {
    C(T ...);
  };
template<template<typename> class X>
  void f() {
    X x1{1};
    X x2{1, 2};
  }
template<typename T>
  using XC = C<T>; // exposition only
template<> void f<C>() {
  XC x1{1}; // OK, deduces C<int>
  XC x2{1, 2}; // error: class template argument deduction fails
}

... ou encore, avec paramètres par défaut :

template< typename T = int>
  struct C {
    C(int);
  };
template<template<typename = long> class X>
  void f() {
    X x{1};
  }
template<typename T = long>
  using XC = C<T>; // exposition only
template<> void f<C>() {
  XC x{1}; // OK, deduces C<long>
}

On examine quelques cas préexistants qui fonctionnent en pratique (on ne voudrait pas briser du code légal). Un enjeu est que certains cas sont très difficiles à analyser, par un compilateur comme par un humain.

(brève pause; on est à la frontière de CWG et de EWG alors c'est difficile)

On remarque que la proposition briserait un exemple pris de CWG 3003 :

template <typename T> struct A { A(T); };

template <typename T, template <typename> class TT = A>
  using Alias = TT<T>; // <-- ceci est méchant; certains pensent que c'est le mal

template <typename T>
  using Alias2 = Alias<T>;

void h() { Alias2 a(42); }
void h2() { Alias a(42); }

L'alias qui est en partie auto référent s'est avéré difficile à implémenter en pratique par les compilateurs. On jongle même avec l'idée de l'interdire.

On finit avec un texte qui permet ceci, qui me semble très bien :

template<typename ... Ts>
  struct Y {
    Y();
    Y(Ts ...);
  };
template<template<typename T = char> class X>
  void f() {
    X x; // OK, deduces Y<char>
    X x0{}; // OK, deduces Y<char>
    X x1{1}; // OK, deduces Y<int>
    X x2{1, 2}; // error: cannot deduce X<T> from Y<int, int>
}
template void f<Y>();

Avec des constantes, on aurait :

template<int>
  struct A { };
template<int I>
  struct C {
    C(A<I>);
  };
template<template<short> class X>
  void f() {
    X x1{A<1>()};
    X x2{A<100000>()};
  }
template<short S>
  using XC = C<S>; // exposition only
template<> void f<C>() {
  XC x1{A<1>()};
  XC x2{A<100000>()};
}

Jason Merrill indique qu'avec ceci, la réflexivité sur ces entités perd l'information sur le template template parameter. Hubert Tong explique que c'est un choix délibéré en vue d'expansions, mais on s'attend à recevoir des complaintes d'usagers éventuellement.

C'est prêt. On amènera ça pour vote samedi. Ce sera un DR.

P2285 – Are default function arguments in the immediate context?

On cherche à savoir si certaines constructions sont valides. Par exemple :

template <class T>
  struct C
  {
    explicit C(T = 1);
  };

C<int> c;    // works
C<int> c(1); // works

std::cout << std::constructible_from<C<std::string>>; // <-- divergences d'implémentation

Le but de la proposition est de clarifier ce qui se passe ici pour réduire les divergences.

Jason Merrill exprime un malaise quant à l'approche proposée car elle change la mécanique d'instanciation des templates. D'autres aspects du langage sont touchés, par exemple les spécifications noexcept, les précondition et les postconditions, certaines parties des lambdas, les annotations, etc. Brian Bi propose l'exemple suivant : https://godbolt.org/z/5oeWz84Eb donc :

template <lclass T>
  auto foo() -> decltype([]() noexcept(noexcept(T() + 1)){}());

template <class T>
  concept canFoo = requires { foo<T>(); };

static_assert(canFoo<int>); // <-- divergences d'implémentation

struct X {};
static_assert(!canFoo<X>); // <-- divergences d'implémentation

Les divergences tiennent au traitement (ou pas) de la clause noexcept dans le immediate context. L'approche proposée semble briser des implémentations légitimes d'instanciations de lambdas et de contrats. Une solution proposée serait d'instancier une lambda en deux temps (d'abord la lambda en soi, ensuite son opérateur ())

(ce sont de longs mais intéressantes débats; pause pour le dîner. Dan Katz est de retour en début d'après-midi alors nous pourrons travailler sur ses propositions)

Brian Bi dit que sa compréhension des échanges avec Jason Merrill est que le souhait est que seules les lambdas devraient avoir un traitement spécial dans ce dossier; les autres volets discutés (paramètres avec valeurs par défaut; clauses noexcept; annotations, contrats, etc.) devraient avoir un traitement uniforme. Jason Merrill semble d'accord pour l'essentiel.

John Spicer pense que dans le cas d'une lambda, il faut substituer l'entièreté de la lambda pour comprendre le type de l'expression ce qui suggère un traitement semblable à celui des classes locales aux fonctions, mais n'est pas convaincu que le même traitement doive être accordé aux contrats. Un enjeu sous-jacent à cette discussion est de savoir si une erreur devrait disparaître à travers SFINAE ou provoquer une hard error, et notre lecture des besoins en ce sens guide en partie nos choix.

L'interaction avec les contrats et les surcharges de fonctions est explorée : si le contrat est évalué à la compilation et la fonction est appelée hors-contrat (pre(expr) expr == false) on aurait, selon la compréhension de John Spicer, un hard error, et ce même si la fonction n'est pas appelée (par exemple, si on cherche à bonne surcharge d'une fonction et qu'on doit évaluer des trucs comme le corps d'une lambda ou une clause noexcept). On n'est pas sûrs que les gens qui ont conçu les contrats ont vu venir ce coup; ça ne semble pas indiqué où que ce soit, mais les membres de CWG sont partagés à ce sujet.

On revient au texte sur la table (les débats – super intéressants – ont duré plus d'une heure!). Ce qui est proposé semble rassembleur : les trucs qui requièrent une instanciation séparée (lambdas, noexcept, valeurs par défaut des paramètres, annotations) ne feraient pas partie du contexte immédiat et provoqueraient, le cas échéant, leurs propres erreurs.

On va passer quelques questions à EWG et à l'auteur officiel de la proposition et revenir dessus, peut-être plus tard cette semaine, avec l'information que ça nous apportera.

(l'un des principaux auteurs des contrats nous informe que l'intention est un hard error, même dans le cas de surcharges de fonctions, mais le débat redémarre... C'est une question de fond, et les contrats sont un sujet qui touche tout le monde!)

Core Issue 3162. Evaluation context of manifestly constant-evaluated expressions

On revient sur ceci :

consteval int f(int p) {
  struct S;
  constexpr int r = /* P */ std::meta::is_complete_type(^^S) ? 1 : 2;
  consteval {
    std::meta::define_aggregate(^^S, {});
  }
  return (p == 0) ? f(p - 1) : r;
}
static_assert(f(1) == 2);

Dan Katz explique que son idée pour l'évaluation de r à chaque passage tient au contexte d'évaluation, qui est conceptuellement distinct à chaque appel. Il pense toutefois qu'on peut le traiter comme un as if et ne l'évaluer qu'une seule fois.

Jason Merrill demande où se trouve le point d'instanciation P concrètement. Davis Herring et Dan Katz expliquent que le consensus pour le moment est « à la fin de l'unité de traduction », mais que ça pourrait changer dans le futur. On s'entend pour remplacer P par Q car P a un autre sens dans la prose qui accompagne l'exemple.

Jason Merrill demande si la réponse à la question std::meta::is_complete_type(^^S) serait différente si on la posait après le bloc consteval, et Dan Katz dit que c'est effectivement le cas.

On retravaille l'exemple :

consteval int f(int p) {
  struct S;
  constexpr int r = /* Q */ std::meta::is_complete_type(^^S) ? 1 : 2;
  consteval {
    std::meta::define_aggregate(^^S, {});
  }
  static_assert(std::meta::is_complete_type(^^S));
  return (p == 0) ? f(p - 1) : r;
}
static_assert(f(1) == 2);

Après la brève pause de l'après-midi, on change légèrement le tout pour que ça porte un peu plus d'information :

consteval int f(int p) {
  struct S;
  constexpr int r = /* Q */ std::meta::is_complete_type(^^S) ? 1 : 2;
  consteval {
    std::meta::define_aggregate(^^S, {});
  }
  static_assert(std::meta::is_complete_type(^^S));
  return (p == 0) ? f(p - 1) : r;
}
consteval {
  if(f(1) != 2)
    throw; // Ok, not evaluated
}

Après quelques heures de travail, on convient que ça peut être amené pour vote samedi. Ouf!

P3692 – How to Avoid OOTA Without Really Trying

Ouf encore : on nous a envoyé un document de 101 pages à examiner à ce stade dans la semaine, et sur un sujet profond... Davis Herring nous explique que sa compréhension est que les entités atomiques Out of Thin Air requises pour réaliser certaines opérations et qui, en théorie, peuvent provoquer des conditions de course ne sont pas, en pratique, un réel problème... le tout avec beaucoup de mathématiques. Heureusement, la version qui nous est transmise se limite à 15 pages (elle a été éditée pour être digeste).

Jens Maurer suggère que, le texte reflétant l'état actuel de la recherche contemporaine sur le sujet, et que le texte a été traité par SG1 et EWG déjà, on ne pourra probablement pas trouver de meilleure terminologie que ce qui est proposé. La principale tâche pour nous est une note, pour laquelle certains identifient des enjeux (éditoriaux). Le texte dit essentiellement (et informellement, dans ce cas) qu'un compilateur ne produira pas de OOTA pour un programme qui ne contient pas de comportement indéfini.

On en discutera en présence des auteurs.

Core Issue 2976. Transferring control out of a function

C'est une proposition de clarification d'un texte qui, de prime abord, semble exclure les return alors que l'intention semble plutôt être de les inclure (le texte auquel ça réfère définit le point où les objets locaux à une fonction sont détruits). L'ajustement de texte proposé est pas mal (et est simple) mais pourrait causer d'autres ennuis dans un contexte plus large, par exemple une double destruction d'objets lors d'une levée d'exception, alors on ajuste légèrement. C'est difficile (de manière peut-être surprenante) de définir clairement l'endroit où une fonction se termine... Roger Orr soulève le cas de longjmp() et suggère une référence croisée.

Après un peu de travail, on décide que c'est prêt et que ce sera un DR. Vote samedi

P3692 – How to Avoid OOTA Without Really Trying

Paul McKenney se joint à nous. Jens Maurer lui demande où on doit insérer ces trucs très abstraits dans le texte du standard (au moins : un numéro de section). On s'entend pour juste après §32.5.4/9, [atomics.order]. On discute de certains choix de termes dans la note comme « runs on real-world hardware » qui semble surtout chercher à éviter des machines abstraites qui auraient un comportement hostile ou déraisonnable et on cherche des alternatives plus à propos.

On relate la présence et le rôle des variables atomiques (en C++, on peut être atomique et volatile, ce que d'autres langages comme Rust ne permettent pas), mais il se trouve que sans variables volatiles, des trucs comme les cartes de crédit ne fonctionnent pas.

On passe presque une heure sur une note non-normative qui décrit les différences fondamentales entre une machine abstraite et une machine « réelle », mais ça vaut la peine et le texte résultant est visiblement meilleur qu'à l'origine, même aux yeux de son auteur. On laisse Paul McKenney faire les retouches, les présenter à LWG et, si tout le monde est content, on le soumettra au vote samedi.

P3726 – Adjustments to Union Lifetime Rules

Barry Revzin se joint à nous pour présenter ceci. Cette proposition corrige des bogues introduits dans une proposition antérieure qui rendait les union plus utiles, surtout dans un contexte constexpr. On joue avec les règles de vie d'un union et de ses membres, alors c'est assez profond. On change entre autres la terminologie, parlant désormais de union subobjects en plus de (et non pas en remplacement de) union members, ce qui a la qualité de rapprocher la terminologie des union de celle des class. On définit aussi ce qu'est un sous-objet inactif (on ne parlait auparavant que du membre actif).

Le traitement des tableaux multidimensionnels et de ce que peut être un inactive subobject dans ce cas demande un peu de temps. Il ne faut pas oublier qu'en gérant la mémoire de manière « serrée » on peut avoir un tableau dont certains éléments sont actifs et d'autres ne le sont pas.

P3795 – Miscellaneous Reflection Cleanup

Barry Revzin explique brièvement l'historique de cette proposition. On trouve un nouvel exemple qui montre la portée d'une annotation :

void f([[=1]] int x);
void f([[=2]] int y) {
  constexpr info rp = parameters_of(^^f)[0];
  constexpr info ry = variable_of(rp);
  static_assert(ry == ^^y);

  static_assert(annotations_of(rp).size() == 2); // both [1, 2]
  static_assert(annotations_of(ry).size() == 1); // just [2]
  static_assert(annotations_of(rp)[1] == annotations_of(ry)[0]); // both yield 2, and it's the same 2
}

On voit ici que les annotations sur la déclaration et sur la définition de f() sont retenues dans la définition quand on regarde annotations_of(rp).

Le reste du document a été vu par d'autres groupes en plus de CWG. On devrait pouvoir soumettre ça au vote samedi; reste juste à décider si c'est soumis par CWG ou LWG. On verra.

À suivre demain...

Jour 3 – 26 mars 2026

Jens Maurer explique que notre tâche principale aujourd'hui inclut l'examen des Core Issues marquées Tentatively Ready, et de traiter certaines questions qui ont été amenées à son attention depuis hier soir. On évacue rapidement quelques NB Comments pour lesquels on n'a pas de proposition de résolution à l'horizon, faisant des Core Issues de ceux-ci pour les traiter ultérieurement.

Les efforts pour « Define "immediate context" » ont été envoyés à EWG.

FR003. Strong Ownership for Modules

Pour le moment, deux déclarations d'une même entité qui ne sont pas mutuellement attetignables (Reachable) dans deux modules distincts mène à une situation de IFNDR. Jason Merrill propose une résolution clarifiant les règles dans ce cas. Avec ses mots, on obtient par exemple :

// "decls.h":
   int f();            // #1, attached to the global module
   int g();            // #2, attached to the global module

 // Module interface of M:
   module;
   #include "decls.h"
   export module M;
   export using ::f;   // OK, does not declare an entity, exports #1
   int g();            // error: matchescorresponds to #2, but attached to M
   export int h();     // #3
   export int k();     // #4

// Other translation unit:
   import M;
   static int h();     // error: matchesconflicts with #3
   int k();            // error: matchesconflicts with #4

J'ai manqué quelques minutes de débats mais les changements terminologiques sont petits et ciblés. On prend tout de même le temps de les regarder en détail.

On va en faire une Core Issue marquée Tentatively Ready, puis l'apporter au vote pour samedi en tant que DR.

P3865 – Class template argument deduction (CTAD) for type template template parameters

Jens Maurer explique que l'on pensait ceci Ready pour samedi, mais Hubert Tong a constaté des problèmes durant la nuit. Hubert Tong explique d'ailleurs qu'on a vérifié tout ce qui était « bon » mais qu'on a échappé des trucs « mauvais », où on gère mal des non-déductions. Il explique le problème et donne une idée d'une possible solution (en gros, il faut exiger que le paramètre problématique soit un Deducible Template).

On discute de la possibilité de faire l'ajustement mineur (ajouter une petite phrase) sans changer le numéro de révision de la proposition et d'expliquer la situation en plénière, mais on décide de simplement faire une nouvelle révision du document (et de trouver comment enlever la révision précédente du Wiki, car c'est un nouveau Wiki et on n'est pas pleinement familières et familiers avec son fonctionnement).

Core Issue 3105. Consteval destructor through immediate escalation

Jens Maurer explique qu'on avait fait de ceci un DR, mais les règles font que les destructeurs peuvent devenir des fonctions immédiates ce que le langage ne permet pas (on ne sait pas quoi faire avec les variables globales) alors on a une restriction à leur sujet. Il se trouve que Tim Song a signalé que cette situation n'est pas utile car si on a un vector<meta::info> on doit en détruire les éléments et ceux-ci sont consteval ce qui mène à un hard error.

On indique en réponse que résoudre ceci dépend de résoudre la question des modèles consteval-only types vs consteval-only values ce qui attendra manifestement à C++29.

Core Issue 3131. Value categories and types for the range in iterable expansion statements

On a ceci :

#include <span>

constexpr int arr[3] = { 1, 2, 3 };
consteval std::span<const int> foo() {
  return std::span<const int>(arr);
}

int main() {
   int r = 0;
   template for (constexpr auto m : foo())
     r += m;
}

// The expansion of this iterable expansion statement contains:
//
//   constexpr auto &&range = foo();
//
// The deduction yields std::span<const int>&& for the type of range, and
//  the non-const lifetime-extended temporary causes constant evaluation to fail.

On regarde le problème qui est bien exploré par la personne ayant soumis le Core Issue. Faudra probablement changer la manière dont on expansion-iterate à travers certains types, entre autres. Une partie de la solution est de faire en sorte que le template for fasse une copie du std::span<const int> à traverser plutôt qu'un std::span<const int>&&.

Hubert Tong indique que la proposition n'est pas claire sur les types qui bénéficieraient (ou pas) d'un tel changement. Jason Merrill signale qu'avec decltype(auto) et une prvalue, on n'a pas de copie en pratique.

On prend le temps d'examiner les cas limites (il y a beaucoup de trucs itérables en C++). Ça semble pas mal dans l'ensemble.

Core Issue 2609. Padding in class types

La Core Issue demande de préciser l'emplacement du Padding dans une classe, à travers un nouveau terme Property of the Implementation qui veut essentiellement dire que c'est implementation-defined, mais sans exiger que les implémentations ne documentent leurs choix. Ça impose toutefois de ne pas changer d'idée avec chaque unité de traduction.

Ça semble Ok. Ready, sous forme de DR.

Core Issue 2744. Multiple objects of the same type at the same address

On a ceci :

#include <new>

struct A { unsigned char buf[1]; };
static_assert(sizeof(A) == 1); // A can fit within A::buf

int main() {
  A x{};
  new (x.buf) A{};
}

Augh! Exploration supplémentaire :

A x{}: // implicit object creation for x.buf
A* p = reinterpret_cast(x.buf); // nailed down A at x.buf

// There is no pointer interconvertibility between x.buf and x, so there must be a second A at x.buf.
//
// Also consider:

struct S {
  unsigned char c[1];
};
unsigned char a[sizeof(S)];
S* ps = new (a) S;  // must create S inside a buffer; now we have two "array of unsigned char" at the same address

// Also consider:

struct B {};
struct A : B {};
struct C : B {};
struct D : A, C { unsigned char x[2]; };

D d;
new (d.x+1) C();

// The A and C base classes must have different offsets (because their B bases must
// have different offsets), thus #2 creates a C object at the offset of the existing
// C base class object.

Faut clarifier ce qu'on veut dire par « deux objets ont la même adresse ». La proposition fonctionne. Ready, DR.

Core Issue 2799. Inheriting default constructors

Soit le code suivant :

struct A { int n; };
struct B : A {
  using A::A;
  B(int);
};

Est-ce que B a un constructeur par défaut? Jens Maurer est d'avis que le texte préexistant couvre ce cas, mais une petite clarification est ajoutée pour aider à la compréhension.

Le texte est pas mal. Ready, DR.

(brève pause du matin)

Core Issue 2947. Limiting macro expansion in pp-module

Dans un monde de modules, ceci ne joue pas gentiment avec le reste du langage :

#define DOT_BAR .bar
export module foo DOT_BAR;

On veut changer la grammaire pour tenir compte de ce cas car l'intention est de pouvoir identifier un nom de module rapidement et sans recours au préprocesseur.

Avec la résolution proposée, on aurait :

 // Exemple :

#define DOT_BAR .bar
export module foo DOT_BAR;   // error: expansion of DOT_BAR; does not begin with ; or [


// Exemple :

#define MOD_ATTR [[vendor::shiny_module]]
export module M MOD_ATTR ;        // OK

// Exemple :

export module a
.b;                         // error: preprocessing token after pp-module-name is not ; or [

// Exemple :

  export module M [[
  attr1,
  attr2 ]] ;                 // OK

// Exemple :

  export module M
  [[ attr1,
  attr2 ]] ;                 // OK

// Exemple :

  export module M; int
  n;                         // OK

Ce sera un DR porté au vote samedi.

Core Issue 2966. Alignment and value representation of std::nullptr_t

C'est amusant ça : le texte du standard spécifie sizeof(std::nullptr_t) mais pas alignof(std::nullptr_t). La proposition est de les faire correspondre tous deux à ceux de void*. Ça correspond à ce que fait C23. Certains mentionnent que cela peut pessimiser les implémentations d'outils traitant du JSON à travers des std::variant par exemple. On va de l'avant malgré tout.

Core Issue 2983. Non-type template parameters are not variables

On indique que le texte les présente comme des variables, mais ce n'est pas correct. On clarifie le tout. Ready, DR.

Core Issue 2992. Labels do not have names

Un autre cas de clarification pour lequel le texte semble correct. Ready, DR.

Core Issue 2995. Meaning of flowing off the end of a function

Notre description de ce qui se produit dans un cas comme le suivant est perfectible 

int foo() {
  struct S {
    ~S() noexcept(false) { throw 1; }
  } s;
}

int main() {
  try {
    foo();
  } catch (int x) {
    return x;
  }
}

La résolution proposée est pertinente. Jason Merrill recommande qu'on l'harmonise avec nos discussions sur le moment où une fonction se termine, tenues hier. C'est une bonne idée, mais ça complique un peu le travail à faire dans ce cas. Notez que l'intérêt ici est que foo() n'a pas de return et serait du comportement indéfini, mais puisqu'elle se termine par une levée d'exception on évite cet irritant.

On traitera ça ulltérieurement, il y a trop à faire pour l'adopter cette semaine.

Core Issue 2996. Impenetrable definition of atomic constraint

Bon, ce qu'on a est indigeste. La proposition est de reformuler pour que ce soit plus raisonnable. Même reformulé, c'est pas de la lecture légère. On retravaille le tout, mais la salle est partagée car plusieurs sont d'avis que le texte préexistant était plus lisible mais on sait que le texte préexistant est incorrect. On a va le mettre de côté et essayer de corriger le texte préexistant au lieu de le remplacer.

Core Issue 3158. Constification for splice-expressions

On a ceci :

void f(int p)
    pre([&] { ++p; return true; }())         // error: unqualified-id 'p' has const type
    pre([&] { ++[:^^p:]; return true; }())   // OK
{
}

Le texte actuel ne fonctionne pas, mais EWG a dit NAD cette semaine... mais a changé d'idée il y a moins d'une heure! Conséquemment, on examine une proposition, écrite il y a deux heures à peine...

CWG 3158 – const-ification of Splice Expressions

On parle ici d'un document pour corriger une décision du passé récent et qui comprendr plusieurs petits changements. L'auteur essaie de faire en sorte que l'idée soit acceptable sur le fond, quitte à retravailler la prose ultérieurement, dans le but d'en arriver à une intégration dans C++26 étant donné qu'il s'agit d'un aspect clé des contrats.

On procède. Vote samedi.

Core Issue 3010. constexpr placement-new should require transparent replaceability

Ceci ne semble pas raisonnable :

struct A { int n; };
struct B : A { int m; };

constexpr int f() {
  B b = {{0}, 0};
  A *p = &b;
  new (p) A{1};     // does not transparently replace *p
  return p->n;      // UB, p refers to out-of-lifetime object
}
constexpr int k = f();

L'enjeu est que dans une fonction constexpr on demande aux compilateurs de diagnostiquer l'accès à n (le placement new est légal, mais l'exigence de rapporter que p->n est UB est déraisonnable en pratique). La proposition n'est pas de le permettre mais bien de permettre un diagnostic plus hâtif du problème. Ajouter la contrainte de transparent replaceability permettrait cela.

Ok, DR.

(pause pour le dîner)

P3726 – Adjustments to Union Lifetime Rules

La terminologie novatrice d'hier a été raffinée. On parle maintenant de union elemental subobjects.

On a une nouvelle fonction std::start_lifetime() qui s'ajoute à des trucs comme std::start_lifetime_as() et std::start_lifetime_as_array().

Exemple :

struct A {
  struct X {
    int i;
    int j;
  };

  struct Y {
    X x1;
    X x2;
  };

  union {
    int i;
    int arr[4];
    Y y;
  };
};

constexpr A v1;       // ok, no constituent values
constexpr A v2{.i=1}; // ok, the constituent values are {v2.i}
constexpr A v3 = []{
  A a;
  std::start_lifetime(a.arr); // ok, arr is now the active element of the union
  new (&a.arr[1]) int(1);
  a.arr[2] = 2;
  return a;
}();                 // ok, the constituent values are {v3.arr[1], v3.arr[2]}
constexpr A v4 = []{
  A a;
  a.y.x1.i = 1;
  a.y.x2.j = 2;
  return a;
}();                 // error: the constituent values include v4.y.x1.j and v4.y.x2.i
//                   // which have erroneous value

Ça semble convenir. On soumet ça au vote samedi.

Core Issue 3171. Codify the strong ownership for modules

Jens Maurer nous montre la Core Issue tout juste créée pour ce dossier. On s'assure de sa conformité.

Core Issue 3029. Confusing note about ordinary character types for aligned memory areas

On a un texte qui est un peu confus et parfois contradictoire quant aux sortes de « caractères » pour fins d'espace à titre de mémoire brute. Le texte proposé vise à clarifier le tout, restreignant pour l'essentiel ces types à unsigned char. Faudra que je sois plus prudent (ça m'arrive d'utiliser char par négligence).

Core Issue 3035. Lambda expressions in anonymous unions

Question « simple » : que se passe-t-il si on fait ceci?

static union {
  int x = [] { return 42; }();
};

Ceci déclare une classe imbriquée dans cet union. Les compilateurs l'acceptent tous. On le permettra.

Core Issue 3058. "Program point" is not defined

Le titre le dit : on a un terme utilisé pour décrire des aspects de la machine abstraite mais que l'on ne définit pas formellement. En gros, il y a un Program Point avant le premier jeton, après le premier jeton et entre toute paire de jetons. Ce sera ça pour le moment.

Core Issue 3088. Clarify macro treatment of identifiers with special meaning

On resserre les règles pour empêcher de modifier le sens de macros qui changeraient le sens de mots clés. C'est désormais Ill-Formed de faire ça. Ça inclut les nouveaux mots clés de C++26 comme pre et post.

Core Issue 3119. for-range-declaration of an expansion-statement as a templated entity

Il faut un template pour générer des expansion statements. La proposition est d'en générer une implicitement pour faire d'un template for un templated context :

struct B {
  int i;
  long l;
};

struct A {
  B b;
};

void f(int i, long l);

int main() {
  template for (auto [ ... e] : A()) {
    f(e...);   // OK
  }
}

C'est cool comme idée! On fait le tour des impacts sur la grammaire et sur la mécanique de génération de code. Ce qui est bien est que le templated context dans ce cas est bien circonscrit et ne fuit pas.

Core Issue 3122. Inadequate value-dependence for reflect-expressions

Ce qui suit devrait être value-dependent mais ne l'est pas en ce moment :

template <typename T>
  consteval void f() {
    T v;
    std::meta::info R = std::meta::type_of(^^v);   // not currently value-dependent
}

Les changements demandés sont localisés et relativement simples. Merveilleux! Ready, vote samedi.

Core Issue 3124. Disallow annotations on block-scope externs and non-unique friend declarations

Ceci est un peu plus volumineux comme changement terminologique. On travaille à la clarification du propos. Ready, on vote samedi.

Core Issue 3125. Token convertibility requirement in #if

On a ceci :

#define F(X) X
#if __has_include(F(<#.h>))
#endif

Ceci est ill-formed mais « passe » par des moyens détournés. On ferme la brèche. Ready, DR.

Core Issue 3126. A module import needs a header-name as a token

Amusant. Ceci :

import "myheader.h";

.. devrait être permis mais, en fait, ne l'est pas parce que les noms d'en-têtes ne sont pas permis dans la grammaire à cet endroit. On corrige cela. Ready, DR.

Core Issue 3128. Potentially-throwing unevaluated operands

Amusant aussi. Examinez ceci :

void f();                          // potentially throwing
bool b = noexcept(noexcept(f()));  // ought to be "true"

Dans un contexte non-évalué, il n'y aura pas d'exception alors b devrait être true mais on n'a pas de mots pour le dire. C'est un tout petit changement. Ready, DR.

Core Issue 3130. Naming function members of anonymous unions

On ne permet pas traditionnellement d'introduire des fonctions nommées (autres que les fonctions membres spéciales) dans un union anonyme, mais avec la réflexivité ça pourrait arriver. Il faut ajouter un peu de terminologie pour éviter cela. La proposition consiste en une série d'interdits.

Shafik Yaghmour demande si on pouvait observer les membres d'un union anonyme (il veut savoir si on provoque un changement de comportement et s'il faut une entrée dans l'annexe C). Hubert Tong explique qu'il y a une manière maudite de le faire à travers decltype(*this) et qu'il existe un Core Issue pour clore cette malédiction. On ne veut pas toucher à l'annexe C car il faudrait au passage dire qu'on ne sait pas ce qui se passe si quelqu'un fait ça en pratique.

Ready, DR.

Core Issue 3132. Unclear disambiguation rule for condition

On parle ici d'un problème de grammaire « pur et dur » avec la production grammaticale condition. On s'assure que le correctif fonctionne. Ready, DR.

Core Issue 3133. Cv-qualified types in built-in operator candidates

On a une liste de candidats pour les conversions dans le langage, mais le texte ne traite pas correctement les cv-qualifiers. On corrige le texte pour indiquer qu'on ne tient pas compte de ces qualifications dans chacun de ces cas. Ça évite d'écrire deux opérateurs de conversion, on vers T et un vers const T par exemple, et de provoquer une ambiguïté.

On fait le tour ces cas un par un pour éviter de faire des bêtises. Ready, DR.

Core Issue 3136. Constant expressions of type void

Avec la réflexivité on peut avoir des constant expressions de type void ce qui n'était pas permis auparavant. C'est pas dramatique mais le texte ne le permet pas.

Le changement à faire (ajouter if any au mot qui parle de la valeur de l'expression) est simple. On examine l'option de faire d'autres mini retouches du genre (des if not void ici et là) mais ça semble envahissant. Ready.

Core Issue 3141. Unique objects from define_static_array

Le texte qu'on a semble parfois contradictoire quant à l'unicité (ou non) de chaque objet produit par std::meta::define_static_array(). On ajoute quelques mots ici et là pour clarifier l'intention. Ready.

Core Issue 3142. Possible expansions of __LINE__ changing over time

L'enjeu est que les valeurs du littéral entier utilisé ne sont pas clairement délimitées. Les clarifications incluent interdiction des littéraux maison et interdiction des délimiteurs.

Core Issue 3148. Definition of "user-declared" special member function

Le texte ne dit pas ce que ce terme signifie, et le définir semble susceptible d'alléger le texte et de le clarifier à plusieurs endroits.

Ready, DR.

P3692 – How to Avoid OOTA Without Really Trying

On examine les changements apportés depuis hier. Tout semble convenable. On porte ça pour vote samedi.

P3865 – Class template argument deduction (CTAD) for type template template parameters

On examine les changements les plus récents. Tout semble convenable. On porte ça pour vote samedi. DR.

P4149 – Define "immediate context"

Cette proposition tardive est écrite en réaction aux votes pris chez EWG sur le sujet plus tôt cette semaine. Elle se compose d'une reformulation de texte préexistant avec plusieurs suppressions et quelques ajouts, et nous devons examiner chacune de ces modifications pour éviter un bris.

On travaille le tout (il y a beaucoup de répétition, mais ça a été écrit dans des délais très restreints alors ça se comprend).

Jason Merrill et John Spicer se demandent si le texte décrit clairement ce qui est assujetti à SFINAE ou non, ce qui est l'un des principaux objectifs du texte (même si c'est pas évident pour les non-initié(e)s). On compare les cas où il faut instancier une lambda, une clause noexcept, un contrat, un paramètre par défaut d'une fonction, etc. pour voir si des cas particulier sont requis. C'est important : une erreur de spécification pourrait empêcher des programmes de compiler! En même temps, on veut quelque chose d'ici demain car beaucoup d'aspects importants du langage dépendent de cette définition.

On constate que les seules clauses noexcept qui doivent être traitées séparément sont celles sur une signature de fonction. On ajuste le texte en conséquence.

On a quelques cas qui peuvent sembler contradictoires sans une priorité claire, alors il faudra clarifier ceux-ci. On pense aussi qu'il peut manquer des trucs comme des classes locales à des function templates.

C'est un travail de près de deux heures qui nous amène à la fin de la journée. Brian Bi s'assure que l'on ait un accord sur les recommandations accumulées en vue de ce qui sera manifestement une mise à jour faite durant la nuit, et demande quelles sont les recommandation de CWG quant aux annotations car il devra retourner devant EWG demain pour les en informer.

(grosse journée!)

Jour 4 – 27 mars 2026

On discute de choses et d'autres, puis on commence à examiner le plan de match de la journée quand quelqu'un vient nous informer que EWG aimerait savoir ce qui se passe avec Core Issue 3112, mais il se trouve que c'est une banalité pour eux alors on les rassure.

Jens Maurer nous explique que la section constant expression du standard a été renommée en constant evaluation, section 7.7, et comprend désormais sept sous-sections. Ouf! Davis Herring a été une force importante derrière ce changement. Ça montre à quel point cet aspect du langage est devenu important au fil des derniers quinze ans. Quelqu'un signale que les gens impliqués dans la réflexivité souhaitent faire disparaître le terme immediate comme dans immediate function, mais ce ne sera pas pour C++26.

Core Issue 3172. Reference to wrong placeholder

Il y a un problème profond qui se cache ici, mais à court terme ce qu'on peut faire est corriger la faute mineure (un C devient un CI).

Core Issue 3170. SFINAE for failed consteval contracts

Ceci concerne un problème découvert cette semaine :

template<class T>
  constexpr int v(T x)
    pre(x > 0)
  {
    return x;        // #1
    // return *T();  // #2
  }

template<int> struct C;

template<class T>
  constexpr int f(C<v(T())> *) { return 1; }  // #3
template<class T>
  constexpr int f(void*) { return 2; }        // #4

static_assert(f<int>((void*)0) == 2);

Joshua Berne pense que ça devrait être un hard error. Jens Maurer fait remarquer que le compilateur ne peut pas éviter d'instancier le cas problématique. John Spicer pense pour sa part que c'est un très gros problème. On débat d'approches à ce problème pendant près d'une heure; je crois comprendre qu'il serait possible de choisir un Build Mode de contrats qui ferait un diagnostic ici sans échouer la compilation, mais je dois avouer ne pas avoir joué avec les contrats suffisamment pour bien voir les contours de ce problème.

On accepte de fermer cette Core Issue en tant que NAD étant donné que cela reflète l'intention. Cela dit, les débats se poursuivent. Certains voient d'autres exemples qu'ils estiment plus représentatifs du problème, d'autres (par exemple Hubert Tong) pensent que LWG va vivre ce problème violemment avec les surchagres de swap().

(Jens Maurer fait remarquer que nous avons déjà 40 propositions en attente de traitement chez CWG pour C++29... Ouf!)

Core Issue 3135. Structured bindings with prvalues from tuples

Le protocole get<I>() utilisé pour accéder au I-ème membre d'un tuple est mal spécifié dans le cas des prvalues si on est dans un contexte constexpr. La proposition est de faire en sorte que les Structured Bindings pour des prvalues n'utilisent pas de types références.

Nos débats font ressortir que T&& (les références de relais) et constexpr ont des interactions déplaisantes. On a probablement un problème plus profond qui se cache ici. Il se trouve que ceci :

constexpr auto [...Is] = std::make_index_sequence<2>();

... est implémenté sous la forme :

constexpr auto e = std::integer_sequence<std::size_t, 0, 1>();
constexpr std::size_t && Is#0 = 0;
constexpr std::size_t && Is#1 = 1;

... où les temporaires résultantes sont modifiables, ce qui n'est pas souhaitable. C'est un effet secondaire a priori insoupçonné de P2686 qui est pour l'essentiel utile. On va créer une Core Issue pour le problème de fond (que devrait-on déduire avec auto&& dans un constexte constexpr?) et on l'examinera un autre jour (c'est un problème qui aura beaucoup de répercussions).

Ready, mais pas un DR

Core Issue 3140. Allowing expansion over non-constant std::array

La proposition change le sens d'un expansion statement sur un tableau même s'il n'est pas constant, ce qui est possible parce que la taille est connue à la compilation. Le résultat serait conceptuellement :

[&] consteval {
    std::ptrdiff_t result = 0;
    for (auto i = begin ; i != end ; ++i, ++result);
    auto b = begin-expr ;
    auto e = end-expr ;
    for (; b != e; ++b) ++result;
    return result;  // distance from begin to end
  }()

On discute longtemps de l'impact de constexpr sur le code généré et du fardeau que cela peut représenter pour un usager. Jakub Jelinek remarque un bogue de spécification dans la proposition, bogue qu'on s'applique à corriger sur-le-champ.

(brève pause matinale; quelques amis dont c'est la première rencontre du comité se joignent à nous, il semble qu'on leur ait recommandé de « vivre l'expérience Core » qui est très différente de ce qui se passe dans les autres pièces)

Core Issue 3149. Rvalues in destructuring expansion statements

Avec ce qui suit, chaque élément sera de type int& avec le texte existant alors que l'intention était d'avoir int&&, int& et int&& respectivement :

auto f() -> std::tuple<int, int&, int&&>

auto g() -> void {
  template for (auto&& elem : f()) {
    ;
  }
}

La proposition est d'utiliser static_cast<decltype(ui)&&>(ui) pour chaque élément ui de elem qui n'est pas un lvalue (notez que ui est un Structured Binding dans le cas couvert par cette proposition). Ready, pas un DR.

Core Issue 3151. Closure types that are final

La proposition met de l'avant que le texte n'empêche pas un Closure Type d'être final. Elle clarifie que ça ne doit pas être le cas. Ready, DR.

Core Issue 3152. Placement of an unrelated complete object in the padding of another complete object

Dans le cas suivant :

struct A {
  char c;
  int i;
} a;

char d;

... il y aura probablement du padding entre a.c et a.i. Rien n'empêche une implémentation d'y placer d, mais cela semble indésirable.

Davis Herring signale qu'on a une prohibition contre deux objets occupant des espaces disjoints à moins que ce ne soit pas observable (intro.object#10), accompagné d'une note non-normative. C'est pas une note très heureuse (intro.object#footnote-16). On essaie de voir si c'est suffisant ici. NAD

Core Issue 3153. Immediate-escalating defaulted comparison

Ces opérateurs ne sont pas immediate-escalating avec le texte existant. La proposition est de corriger cela. C'est tout petit. Ready, DR.

Core Issue 3155. Escalation of virtual functions

On interdit les spécialisations de fonctions membres virtuelles non-consteval par des fonctions membres consteval, mais le texte ne tient pas compte de l'immediate escalation. La proposition est de clarifier la situation et inscrire cet interdit dans le texte. C'est tout petit. Ready, DR (mais qui mentionne un nouveau mécanisme). Il se peut que cet interdit disparaisse avec C++29, mais on verra une fois rendus là.

Core Issue 3156. Handling of deleted functions in unevaluated lambda-captures

On a une divergence d'implémentation :

 struct C {
  C(int) = delete;
  C(){};
};

decltype([b = C(3)](){ return 4; }()) x; //MSVC accepts; gcc and clang reject

En pratique, c'est un bogue de MSVC (b n'est pas utilisé dans la lambda, mais il faudrait détecter le problème dans la capture malgré tout) mais la proposition améliore le texte du standard alors on l'examine. On retire une phrase un peu mal avisée et redondante, mais Ok pour le reste. Ready, DR.

Core Issue 3157. Missing handling of operator new[] for deallocation function template matching

Il manque un cas dans le texte existant. On remplace operator new par allocation function à quelques endroits, essentiellement. Ready, DR.

D4143R0 – Constant evaluation when?

On parle d'une proposition de clarification du « moment » où se produit une constant evaluation. C'est un document de réflexion profonde sur la mécanique d'évaluation des expressions. On passe beaucoup de temps à lire, débattre du choix des mots, examiner si les tournures au pluriel sont trop obscures, etc.

(après une heure et plus de travail et de discussion, on prend une pause dîner; j'en profite pour faire une brève sieste)

(on poursuit sur D4143)

Le terme trial evaluation, utilisé informellement pour décrire certains aspects du fonctionnement des compilateurs, a été changé pour determination pour éviter de donner l'impression qu'il y ait une évaluation (ce n'est pas le cas)

Travailler sur ce genre de texte est très difficile, même pour les expert(e)s dans la salle. On essaie de mettre en place un modèle qui nous permettra d'en arriver à une forme de perspective partagée de ce qui se passe dans la machine abstraite de C++ quand on a un contexte constexpr, or la machine abstraite est un modèle d'exécution et ce qui se passe à la compilation y est opaque. On en vient au point où la partie qui offre un modèle de l'évaluation d'une expression constexpr et son passage à l'exécution est retiré malgré sa pertinence, mais parce que c'est trop difficile d'accès pour l'aspect pédagogique souhaité pour cette proposition.

On garde le reste de la proposition, et on ouvre une Core Issue pour la partie qui n'a pas reçu l'assentiment de la salle.

D4149 – Define "immediate context"

Brian Bi nous explique que EWG ne voulait pas trancher quant au moment où les annotations sont instanciées. Pour cette raison, la proposition a été dépouillée de toute référence aux annotations.

Un des questionnements que nous avons avec la proposition est le risque d'instancier plus de templates que l'on ne le voudrait. On essaie de considérer les cas décrits dans la proposition un à un pour voir ce qui se passera en pratique.

On a un nouveau terme grammatical, separately instantiated construct, pour couvrir les trucs qui sont instanciés séparément des classes ou des fonctions que l'on instancie et qui ne dépendent pas de celles-ci.

Il y a un malaise quant à certains aspects du texte proposé. En particulier, le immediate context est, en pratique, ce qui est fait lors d'une substitution dans un template, et certains sont d'avis que le texte sur la table ne dit pas tout à fait cela. Hubert Tong pose le problème sous la forme d'un template sur T* pour lequel on substituerait un type spécifique pour T et ce type serait une référence : le texte permet-il de dire qu'on forme un pointeur sur une référence?

On met ça de côté pour le moment, mais l'essentiel est bon.

(brève pause d'après-midi; les ami(e)s à Croydon parlent de la collation offerte là-bas, une sorte de gâteau chocolat-Guiness... Mioum!)

Au retour, Hubert Tong propose une formule alternative pour la définition du immediate context. On décide aussi d'aborder son questionnement pré-pause avec un exemple :

template<typename T>
  T* fun(T && v); // #1: the deduction substitution locus is the function type « function
                          //     of (rvalue reference to T) returning pointer to T »

void fun(...); // #2

void test() {
  int i{};
  fun(i); // selects #2 (forming the pointer to reference to int fails in #1)
}

Joshua Berne propose aussi ceci :

template <typename T, typename U, typename V>
T* fun(T&& y, U&& u, V&& v)
  noexcept( sizeof(U*) > 0)
  pre(sizeof(V*) > 0);
int* fun(...);

int i;
int *j = fun(i,2,3);  // OK
int *k = fun(1,i,3);  // error
int *l = fun(1,2,i); // error

On retravaille ensuite la définition du immediate context pour en clarifier la temporalité et la chronologie des instanciations.

Après plusieurs heures, c'est fait. Ready, on l'amène au vote demain.

P3769 – Clarification of placement new deallocation

Le texte qui décrit quelle fonction de déallocation sera utilisée pour une fonction d'allocation donnée lorsque le constructeur de l'objet échoue manquait d'amour. Entre autres, le texte était inadéquat pour les fonctions de déallocations supprimées. Avec la proposition, si aucune fonction de déallocation convenable n'est disponible, alors aucune n'est choisie tout simplement.

La proposition a besoin d'un peu de travail. On parle d'un processus de lookup mais il n'est pas décrit alors on cherche à spécifier la gestion du premier paramètre.

Avec la proposition, on aurait ceci :

struct A {};
struct T { T(); };

void* operator new(std::size_t s, A& al); // #1

template<int = 0>
void operator delete(void* p, A& al); // #2

A al;
T *p = new (al) T; // Uses #1 and #2.

... et cela :

template<int I>
struct A {};
struct T { T(); };

void* operator new(std::size_t s, A<0>& al); // #1

template<int I>
void operator delete(void* p, A<I>& al);
void operator delete(void* p, A<0>& al);

A<0> al;
T *p = new (al) T; // Uses #1. No deallocation function is selected as two candidates remain

... de même que cela :

template<int I>
struct A {};
struct T { T(); };

void* operator new(std::size_t s, A<0>& al); // #1

template<int I> requires (I > 0)
void operator delete(void* p, A<I>& al);
void operator delete(void* p, A<0>& al); // #2

A<0> al;
T *p = new (al) T; // Uses #1 and #2.

Après environ une heure de travail, on décide d'aller de l'avant. Ready, DR.

Core Issue 2765. Address comparisons between potentially non-unique objects during constant evaluation

On revient sur l'exemple suivant :

constexpr const char *f() { return "foo"; }

constexpr bool b1 = "foo" == "foo";   // error: non-constant
constexpr bool b2 = f() == f();       // error: non-constant
constexpr const char *p = f();
constexpr bool b3 = p == p;           // OK, value of b3 is true
constexpr bool b4 = "xfoo" + 1 == "foo\0y"; // error: non-constant; string literal object could contain "xfoo\0y"
constexpr bool b5 = "foo" == "bar";   // OK, value of b5 is false
constexpr bool b6 = "foo" == "oo";    // OK, value of b6 is false; offsets would be different in a merged string literal object

constexpr std::initializer_list<int *> il1 = { (int *)nullptr };
constexpr std::initializer_list<unsigned long> il2 = { 0 };
constexpr bool b7 = il1.begin() == (void *)il2.begin();   // error: non-constant

On nous fait remarquer que la comparaison de tableaux bruts avec == ne compile plus depuis C++26 (bonne nouvelle!) alors b1, b5 et b6 doivent être ajustés. CWG étant CWG, on décide de régler le problème de trois façons différentes (j'adore Core!) :

constexpr const char *f() { return "foo"; }

constexpr bool b1 = +"foo" == "foo";   // error: non-constant
constexpr bool b2 = f() == f();       // error: non-constant
constexpr const char *p = f();
constexpr bool b3 = p == p;           // OK, value of b3 is true
constexpr bool b4 = "xfoo" + 1 == "foo\0y"; // error: non-constant; string literal object could contain "xfoo\0y"
constexpr bool b5 = "foo" == "bar" + 0;   // OK, value of b5 is false
constexpr bool b6 = (const char*) "foo" == "oo";    // OK, value of b6 is false; offsets would be different in a merged string literal object

constexpr std::initializer_list<int *> il1 = { (int *)nullptr };
constexpr std::initializer_list<unsigned long> il2 = { 0 };
constexpr bool b7 = il1.begin() == (void *)il2.begin();   // error: non-constant

On achète. Ready.

Core Issue 3129. Clarify which floating-point-literals are valid

La question est simple : ceci est-il bien formé?

float x = 1e100000000000000000000000000000000000000000000000.f;

La résolution proposée mène à ceci, qui suppose que la plateforme support std::float32_t :

std::float32_t x = 0.0f32;          // value 0 is exactly representable
std::float32_t y = 0.1f32;          // rounded to one of two values nearest to 0.1
std::float32_t z = 1e1000000000f32; // either greatest finite value or positive infinity

Ready, DR.

Les dernières minutes de la semaine chez CWG permettent de discuter de trucs d'ordre administratif (horaire des téléconférences, présentation des Core Motions demain, ce genre de truc). On finit sur un truc amusant qui a été écrit aujourd'hui...

Core Issue 3173. Remove misleading footnote about as-if rule

On a blagué là-dessus aujourd'hui, mais on a une note non-normative qui semble faire croire que la règle du as-if ne s'applique qu'à certains aspects du standard. On va supprimer ça.

Core Issue 2666. Lifetime extension through static_cast

On allait la regarder mais Brian Bi nous dit que le Wording n'est pas prêt. Ce sera pour une autre fois.

Core Issue 2660. Confusing term "this parameter"

On a un passage qui parle du this parameter, ce qui semble un peu mêlant. Le terme implicit object est plus convenable. Ready, DR.

Core Issue 3143. Incorrect statement about enumerators for C23

Les standards de C et C++ ont divergé pour les énumérateurs avec C23, car en C++ le type d'un énumérateur est le type énuméré alors qu'en C, c'est toujours un type entier :

enum e { A };
void f() {
  auto x = A;
  int *p = &x;   // valid C, invalid C++
}
sizeof(A) == sizeof(int)  // in C
sizeof(A) == sizeof(e)    // in C++
/* and sizeof(int) is not necessarily equal to sizeof(e) */

Ready, mais pas un DR.

Core Issue 3145. Uniqueness of annotations

Chaque annotation provoque quelque chose de nouveau dans notre grammaire, mais la question est de savoir si chaque instanciation d'un template annoté provoque une annotation distincte :

template<int> int x [[=1]];
template<int A> int y [[=A]];
static_assert(annotations_of(^^x<0>) == annotations_of(^^x<1>)); // #1
static_assert(annotations_of(^^y<0>) == annotations_of(^^y<1>)); // #2

On avait déjà ceci, où f() a une annotation et g() en a cinq :

[[=1]] void f();
[[=2, =3, =2]] void g();
void g [[=4, =2]] ();

... de même que ceci :

 template<class T>
  [[=T::type()]] void f(T t);
void f(int);
void g() {
  f(0);       // OK
  f('0');     // error, ...
}

On souhaite ajouter ceci :

template<int> int x [[=1]];
static_assert(annotations_of(^^x<0>) != annotations_of(^^x<1>));   // OK

Malheureusement, le temps nous manque. Celle-ci ira à C++29.

Jour 5 – 28 mars 2026

Après quelques irritants audio, Nina Ranns nous accueille.

orts des groupes d'études

ABI Group : pas de rapport à offrir.

Admin Group : donne les chiffres pour la participation. Au total, 34 National Bodies cette semaine. Wow!

Rapp

SG1: Concurrency and Parallelism Study Group : Olivier Giroux nous annonce que ce sera son dernier meeting après 15 ans de participation. Il relate que SG1 a débuté en 2008 avec Hans Boehm comme premier Chair. Olivier est entrée en 2011 et est Chair depuis 2018. Ruslan Arutyunyan sera le Chair désormais. Parmi les gros dossiers, après 15 ans, on pourra bientôt remplacer std::async() et offrir des seqlocks. Que dire des Fibers? Que retient-il? Faut accepter la rétroaction du groupe plutôt que la combattre. On cherche la « vision WG21 » de votre idée, elle cesse de vous appartenir (il pense à std::concurrent_queue entre autres). Olivier donne ensuite des conseils aux Chairs du futur de manière générale, en particulier sur la prise de votes pour accroître le consensus et pour éviter les votes qui mettront l'auteur ou le groupe dans le pétrin. Il offre ensuite une vision sur la culture des groupes, qui varie selon les groupes et est influencée par la personne jouant le rôle de Chair. Ruslan Arutyunyan promet ensuite de faire de son mieux pour continuer le travail entrepris par Olivier et rend hommage à ce dernier.

SG2: Modules Study Group : inactif cette semaine

SG3: File System Study Group : inactif cette semaine

SG4: Networking Study Group : inactif cette semaine

SG5: Transactional Memory : inactif cette semaine

SG6: Numerics : le groupe s'est rencontré la moitié de la semaine (une grosse semaine pour ce groupe!) avec une salle pleine et des participant(e)s à distance. Beaucoup de discussions sur les nombres à virgule flottante et les standards IEEE. Beaucoup de volontaires mais peu de propositions. On liste les dossiers sur lesquels on a travaillé.

SG7: Reflection : inactif cette semaine

SG8: Concepts : inactif cette semaine

SG9: Ranges : inactif cette semaine

SG10: Feature Test : inactif cette semaine

SG12: Undefined and Unspecified Behavior : inactif cette semaine

SG13: I/O : inactif cette semaine

SG14: Low Latency : inactif cette semaine, mais on travaille chaque mois sur la proposition de Patrice Roy et sur les exceptions pour systèmes embarqués. Les interactions avec Networking et les exécuteurs nous occuperont au cours des prochains mois

SG15: Tooling : quelques travaux cette semaine

SG16: Unicode : inactif cette semaine mais on progresse. Tom Honermann quitte le poste de Chair après sept ans et sera remplacé par Steve Downey. Il nous montre que SG16 a adopté un caractère Unicode, soit le caractère de remplacement!

SG17: EWG Incubator : inactif cette semaine

SG18: LEWG Incubator : deux après-midi cette semaine, et nous finissons nos rencontres à l'heure! Nous avons fini de traiter la bibliothèque Quantities and Units sur laquelle nous travaillons depuis Tokyo.

SG19: Machine Learning : inactif cette semaine, mais on travaille chaque mois. Nos gros sujets sont les statistiques et le Machine Learning. Nous travaillons dans une acception plus globale de C++ et de l'intelligence artificielle contemporaine, C++ étant le substrat sur lequel le reste du monde de l'IA contemporaine est construit.

SG20: Education : rencontre mardi après-midi. Les Teaching Guidelines s'en viennent. Nous avons discuté de l'adaptation de l'enseignement à l'avènement de l'IA. Nous avons discuté de l'écosystème qui complique l'accès à C++ pour les débutant(e)s

SG21: Contracts : inactif cette semaine

SG22: C/C++ Liason : inactif cette semaine

SG23: Safety and Security : nous nous sommes rencontrés mercredi matin et nous avons traité deux propositions (il y en avait quatre mais l'auteur des deux autres n'était pas présent). Nous planifions être la force derrière le développement des Profiles.

Rapports des groupes de travail

EWG : grosse semaine, traitant toutes les propositions pour C++26 (une seule n'eut pas de consensus), incluant 13 dossier impliquant une interaction avec CWG. On garde les contrats! On a abordé 27 propositions pour C++29. L'après-midi de vendredi (quatre heures) fut consacré au Memory Safety, et il y avait des gens debout dans la salle, incluant 83 personnes votantes.

LEWG : on fait la (longue!) litanie des dossiers traités, et il y en a plusieurs dizaines. Le groupe a traité 248 LEWG Issues, c'était une grosse semaine! On met de l'avant l'importance de la collaboration avec LWG.

CWG : on a traité tous les NB Comments sur la table, à travers plusieurs papiers. Quelques votes désignés DR à Kona l'ont été incorrectement et nous aimerions corriger cette situation aujourd'hui. La Core Issue 3158 sera traitée séparément des autres (vote 8) à la demande de certaines personnes dans la salle. Nous avons traité 412 NB Comments au total, incluant lors des téléconférences.

LWG : on a travaillé très fort et on n'a pu traiter que des dossiers pour C++26, rien pour C++29. Au mieux de ma connaissance nous avons traité tous les NB Comments pour C++26. On a peut-être battu notre record pour le nombre de votes à tenir. Au total, on soumet environ cent changements pour votre approbation cette semaine.

Votes proposés par CWG

Les votes amenés par CWG cette semaine sont les suivants.

1. Correct the categorization of core issue 3081 to not be a Defect Report and of core issues 3082 and 3110 to be Defect Reports. (The resolutions of all three core issues were adopted at the November, 2025 WG21 meeting.)

Adopté

2. Accept as Defect Reports and apply the proposed resolutions of all issues except issues 3088, 3119, 3122, 3123, 3124, 3131, 3135, 3140, 3141, 3143, 3145, 3149, 3162, and 3172 in P4160R0 (Core Language Working Group "ready" Issues for the March, 2026 meeting) to the C++ Working Paper.

Adopté

3. Apply the proposed resolutions of issues 3088, 3119, 3122, 3123, 3124, 3131, 3135, 3140, 3141, 3143, 3145, 3149, 3162, and 3172 in P4160R0 (Core Language Working Group "ready" Issues for the March, 2026 meeting) to the C++ Working Paper.

Vote demandé. C'est rare pour ce genre de vote alors on demande laquelle ou lesquelles des Core Issues pose problème pour scinder le vote et traiter ce qui irrite séparément. On nous indique que 3141 brisera du code existant.

Avec cette scission (ajout du vote 13, plus bas), pas de vote. Adopté.

4. Accept as a Defect Report and apply the changes in P3924R1 (Fix inappropriate font choices for "declaration") to the C++ Working Paper. This addresses ballot comment US 11-400.

Adopté

5. Accept as a Defect Report and apply the changes in P4136R2 (#line is not in line with existing implementation) to the C++ Working Paper. This addresses ballot comment FR-009-108.

Adopté

6. Accept as a Defect Report and apply the changes in P4004R1 (Reconsider CWG 1395 "Partial ordering of variadic templates reconsidered") to the C++ Working Paper.

Adopté

7. Accept as a Defect Report and apply the changes in P3865R3 (Class template argument deduction (CTAD) for type template template parameters) to the C++ Working Paper.

Adopté

8. Apply the changes in P3598R0 (CWG 3158 — const-ification of Splice Expressions) to the C++ Working Paper.

Vote demandé. Consensus pour, mais quelques noms importants contre. Intéressant

9. Apply the changes in P3726R2 (Adjustments to Union Lifetime Rules) to the C++ Working Paper.

On signale que cela adresse DE 087. On n'a pas à changer le libellé, mais on le fait

Adopté

10. Accept as a Defect Report and apply the changes in P4143R0 (Constant evaluation when?) to the C++ Working Paper. This partially addresses ballot comment US 33-065.

Adopté

11. Accept as a Defect Report and apply the changes in P4149R1 (Define "immediate context") to the C++ Working Paper. This addresses ballot comment US 54-100 and core issues 1844 and 2296.

Vote demandé. Consensus pour

12. Accept as a Defect Report and apply the changes in P3769R1 (Clarification of placement new deallocation) to the C++ Working Paper.

Adopté

13. Apply the proposed resolutions of issue 3141 in P4160R0 (Core Language Working Group "ready" Issues for the March, 2026 meeting) to the C++ Working Paper.

Vote demandé. Consensus pour

Votes proposés par LWG

Les votes amenés par LWG cette semaine sont les suivants. Il y avait une erreur dans le libellé du vote 37 mais la proposition, elle, est correcte.

1. Apply the changes in P4145R0 (C++ Standard Library Ready Issues to be moved in Croydon, Mar. 2026) to the C++ working paper.

Adopté

2. Apply the changes in P4146R0 (C++ Standard Library Immediate Issues to be moved in Croydon, Mar. 2026) to the C++ working paper.

Adopté

3. Apply the changes in P3690R1 (Consistency fix: Make simd reductions SIMD-generic) to the C++ working paper. This addresses ballot comment AT8-279.

Adopté

4. Apply the changes in P3844R4 (Reword [simd.math] for consteval conversions) to the C++ working paper. This addresses ballot comment DE-286.

Adopté

5. Apply the changes in P3932R0 (Fix LWG4470: Fix integer-from in [simd]) to the C++ working paper.

Adopté

6. Apply the changes in P4012R1 (Value-preserving consteval broadcast to simd::vec) to the C++ working paper. This addresses ballot comment DE-286.

Adopté

7. Apply the changes in P3886R0 (Wording for AT1-057) to the C++ working paper. This addresses ballot comment AT 1-057.

Adopté

8. Apply the changes in P3936R1 (Safer atomic_ref::address (FR-030-310)) to the C++ working paper and update the value of the __cpp_lib_atomic_ref macro. This addresses ballot comment FR-030-310.

Adopté

9. Apply the changes in P4140R0 (Proposed resolution for US70-126: allow incomplete types in type_order) to the C++ working paper. This addresses ballot comment US 70-126.

Adopté

10. Apply the changes in P3373R4 (Of Operation States and Their Lifetimes) to the C++ working paper. CA-338.

Adopté

11. Apply the changes in P3986R1 (A Wording Strategy for Inlinable Receivers) to the C++ working paper. This addresses ballot comment CA-318.

Adopté

12. Accept as a Defect Report and apply the changes in P3059R2 (Making user-defined constructors of view iterators/sentinels private) to the C++ working paper. This addresses ballot comment GB 09-257.

Adopté

13. Accept as a Defect Report and apply the changes in P3725R3 (Filter View Extensions for Safer Use, Rev 3) to the C++ working paper. This addresses ballot comments AT9-249, RU-250, DE-251.

Adopté

14. Apply the changes in P3828R1 (Rename the to_input view to as_input) to the C++ working paper. This addresses ballot comment DE-248.

Vote demandé. Consensus pour

15. Apply the changes in P3795R2 (Miscellaneous Reflection Cleanup) to the C++ working paper. This addresses ballot comments US 42-078 and US 85-150 and US 122-184 and US 128-192 and US 95-202 and US 131-195.

Adopté

16. Apply the changes in P3948R1 (constant_wrapper is the only tool needed for passing constant expressions via function arguments) to the C++ working paper. This addresses ballot comments FR-019-210 and FR-021-218.

Adopté

17. Apply the changes in P3978R3 (constant_wrapper should unwrap on call and subscript) to the C++ working paper.

Adopté

18. Apply the changes in P3961R1 (Less double indirection in function_ref) to the C++ working paper. This addresses ballot comment RU-220.

Adopté

19. Apply the changes in P3981R2 (Better return types in std::inplace_vector and std::exception_ptr_cast) to the C++ working paper. This addresses ballot comments PL-006 and US 68-122 and US 150-228 and GB 08-225.

Quelqu'un demande de résumer l'intention brièvement. On procède

Adopté

20. Apply the changes in P4022R0 (Remove try_append_range from inplace_vector for now) to the C++ working paper. This addresses ballot comment PL-006.

Adopté

21. Apply the changes in P4037R1 (Supporting signed char and unsigned char in random number generation) to the C++ working paper. This addresses ballot comment RU-272.

Adopté

22. Apply the changes in P3450R1 (Extend std::is_within_lifetime) to the C++ working paper. This addresses ballot comment US 82-145.

Adopté

23. Apply the changes in P3982R2 (Split strided_slice into extent_slice and range_slice for C++26) to the C++ working paper. This addresses ballot comment PL-007.

Adopté

24. Apply the changes in P4144R1 (Remove span’s initializer_list constructor for C++26) to the C++ working paper.

Adopté (je m'attendais à de la résistance ici)

(brève pause)

25. Apply the changes in P3804R2 (Iterating on parallel_scheduler) to the C++ working paper. This addresses ballot comment RO 4-395.

Adopté

26. Apply the changes in P3787R2 (Adjoints to "Enabling list-initialization for algorithms": uninitialized_fill) to the C++ working paper. This addresses ballot comment FR-027-267.

Adopté

27. Apply the changes in P3842R2 (A conservative fix for constexpr uncaught_exceptions() and current_exception()) to the C++ working paper. This addresses ballot comments PL-012 and GB 03-119 and DE-120 and US 67-118 and FI-121.

Adopté

28. Apply the changes in P3826R5 (Fix Sender Algorithm Customization) to the C++ working paper. This addresses ballot comments US 207-328 and US 202-326 and FR-031-219 and FI-331 and CA-358.

Adopté

29. Apply the changes in P3980R1 (Task’s Allocator Use) to the C++ working paper. This addresses ballot comments US 254-385 and US 253-386 and US 255-384 and US 261-391.

Adopté

30. Apply the changes in P4156R0 (Rename meta::has_ellipsis_parameter to meta::is_vararg_function) to the C++ working paper. This addresses ballot comment FR-017-155.

On signale que la décision de soumettre ceci au vote a été prise tardivement hier et que certains sont préoccupés (on nous dit que « la maison n'est pas en feu », mais qu'il y a des préoccupations). L'enjeu est le suffixe _function qui diverge un peu de ce qui est représenté en termes de Core Wording.

Vote demandé. Consensus pour

31. Apply the changes in P3953R3 (Rename std::runtime_format) to the C++ working paper.

Adopté

32. Apply the changes in P4052R0 (Renaming saturation arithmetic functions) to the C++ working paper. This addresses ballot comment FR-026-265.

Adopté

33. Apply the changes in P3941R4 (Scheduler Affinity) to the C++ working paper. This addresses ballot comments US 232-366 and US 233-365 and US 234-364 and US 235-363 and US 236-362.

Adopté

34. Apply the changes in P3856R8 (New reflection metafunction - is_structural_type) to the C++ working paper. This addresses ballot comment US 49-090.

Adopté

35. Apply the changes in P3927R2 (task_scheduler support for parallel bulk execution) to the C++ working paper. This addresses ballot comment US 238-368.

Adopté

36. Apply the changes in P4151R1 (Rename affine_on) to the C++ working paper.

Adopté

37. Apply the changes in P4159R0 (Make sender_in sender_to and receiver_of exposition-only) to the C++ working paper.

Adopté

38. Apply the changes in P4154R0 (Renaming various execution things) to the C++ working paper. This addresses ballot comments US 205-320 and RO 4-395.

Adopté

Votes proposés par WG21

Les votes pour WG21 sont les suivants.

1. Adopt P1000R7 "Proposed C++ IS schedule".

Adopté (c'est le même modèle qu'à l'habitude, cycle de trois ans). On accepte avec amendements mineurs (il y avait des petites erreurs cléricales)

On commence officiellement le travail sur C++29!

2. Direct the Convener to transmit paper N5036 “ISO/IEC JTC1/SC22/WG21 White Paper, Extensions to C++ for Transactional Memory Version 2” for publication as an SC 22 white paper.

On explique qu'on a déjà voté ceci, mais que rien ne s'est passé chez SC22 parce que notre intention n'était pas claire à leurs yeux. On veut être limpides

Vote demandé. Consensus pour

3. Appoint a review committee composed of Daniel Krügler, Jonathan Wakely, Neelofer Banglawala, and Shafik Yaghmour to approve the correctness of the C++ working paper as modified by the polls approved at this meeting, and direct the Convener to transmit the approved updated working paper for DIS ballot.

Un représentant de pays énonce son opposition au standard sous sa forme actuelle, signalant que les contrats lui semblent dommageables pour le langage.

Quelqu'un signale que la formulation du vote ne dit pas clairement que les éditeurs pourront faire des changements. On nous rappelle que c'est un libellé standard, le même que d'habitude

Vote demandé. Consensus pour. C++26 est complet!

On prend la photo de groupe, participants Zoom inclus. J'ai notre Conure, Patapon, sur mon épaule (il a participé toute la semaine)

Autres rapports

Direction group : c'est un groupe avec direction rotative. Daveed Vandevoorde sera le Chair pour la prochaine année. Il présente les grandes lignes des efforts attendus pour C++29 et pour la prochaine décennie.

Les prochaines rencontres seront à Brno (Czechie), N5011, le 8 juin 2026, puis à Búzios (Rio de Janeiro, Brésil), N5021, le 16 novembre 2026

On remercie les Chairs qui font un travail colossal. On gère les derniers dossiers administratifs (transport de l'équipement et tout), puis un ferme les livres vers 7 h 20 heure de Montréal (12 h 20 à Londres). Enfin, on félicite la nouvelle équipe adminsitrative qui a fait un excellent travail toute la semaine durant.


Valid XHTML 1.0 Transitional

CSS Valide !