Il n'y a pas si longtemps, les expressions-requises (la phrase introduite par la seconde requiert) n'était pas autorisée dans les expressions-contraintes (la phrase introduite par la première requiert). Il ne pouvait apparaître que dans les définitions de concept. En fait, c'est exactement ce qui est proposé dans la section de ce document où cette allégation apparaît.
Cependant, en 2016, il a été proposé d'assouplir cette restriction [Note de la rédaction: P0266 ]. Notez la suppression du paragraphe 4 dans la section 4 du document. Et donc est né oblige.
Pour dire la vérité, je n'avais jamais mis en œuvre cette restriction dans GCC, donc cela avait toujours été possible. Je pense que Walter a peut-être découvert cela et l'a trouvé utile, ce qui a conduit à cet article.
De peur que quiconque pense que je n'étais pas sensible à l'écriture exige deux fois, j'ai passé un certain temps à essayer de déterminer si cela pouvait être simplifié. Réponse courte: non.
Le problème est qu'il y a deux constructions grammaticales qui doivent être introduites après une liste de paramètres de modèle: très souvent une expression de contrainte (comme P && Q
) et parfois des exigences syntaxiques (comme requires (T a) { ... }
). C'est ce qu'on appelle une expression d'exigences.
Le premier requiert introduit la contrainte. Le second requiert introduit l'expression require. C'est juste la façon dont la grammaire se compose. Je ne trouve pas du tout cela déroutant.
J'ai essayé, à un moment donné, de les réduire à un seul besoin. Malheureusement, cela conduit à des problèmes d'analyse très difficiles. Vous ne pouvez pas dire facilement, par exemple si un (
après le requiert indique une sous-expression imbriquée ou une liste de paramètres. Je ne crois pas qu'il y ait une désambiguïsation parfaite de ces syntaxes (voir la justification de la syntaxe d'initialisation uniforme; ce problème est là aussi).
Vous faites donc un choix: make requiert introduire une expression (comme c'est le cas maintenant) ou lui faire introduire une liste paramétrée d'exigences.
J'ai choisi l'approche actuelle car la plupart du temps (comme presque 100% du temps), je veux autre chose qu'une expression-oblige. Et dans le cas extrêmement rare où je voulais une expression requise pour les contraintes ad hoc, cela ne me dérange vraiment pas d'écrire le mot deux fois. C'est un indicateur évident que je n'ai pas développé une abstraction suffisamment solide pour le modèle. (Parce que si j'avais, il aurait un nom.)
J'aurais pu choisir de faire en sorte que les demandes introduisent une expression requise. C'est en fait pire, car pratiquement toutes vos contraintes commenceraient à ressembler à ceci:
template<typename T>
requires { requires Eq<T>; }
void f(T a, T b);
Ici, la 2ème demande est appelée une exigence imbriquée; il évalue son expression (l'autre code du bloc de l'expression requires-expression n'est pas évalué). Je pense que c'est bien pire que le statu quo. Maintenant, vous obtenez d'écrire exige deux fois partout.
J'aurais pu aussi utiliser plus de mots-clés. C'est un problème en soi - et ce n'est pas seulement la perte de vélos. Il pourrait y avoir un moyen de "redistribuer" les mots-clés pour éviter la duplication, mais je n'ai pas sérieusement réfléchi. Mais cela ne change pas vraiment l'essence du problème.
noexcept(noexcept(...))
.