Lors de la réunion, les modifications et ajouts suivants au projet C ++ 20 :
- Amélioration de la reconnaissance contextuelle du « module » et de « l'importation » pour permettre aux outils non compilateurs tels que les systèmes de génération de déterminer plus facilement les dépendances de génération.
- Ajout de plusieurs nouveaux algorithmes de classement.
- Ajout de ranges::ssize.
- Affinage de la signification de static et inline dans les interfaces de module (P1779 et P1815).
- Résolution de nombreux problèmes de langage et de bibliothèque de base et amélioration substantielle des spécifications.
Les éléments suivants sont des fonctionnalités clés dans C++20 :
- Les Modules.
- Les Coroutines.
- Les Concepts.
- Les Ranges.
- Les constexprification: constinit, consteval, std::is_constant_evaluated, constexpr allocation, constexpr std::vector, constexpr std::string, constexpr union, constexpr try and catch, constexpr dynamic_cast and typeid.
- std::format("For C++{}", 20)
- operator<=>
- Macros de test de fonctionnalités.
- std::span
- std::source_location.
- std::atomic_ref.
- std::atomic::wait, std::atomic::notify, std::latch, std::barrier, std::counting_semaphore, etc.
- std::jthread and std::stop_*.
Comme l’explique Herb Sutter, président du comité de normalisation ISO C++, les Modules constituent une nouvelle alternative aux fichiers d’entête et apportent un certain nombre d’améliorations clés notamment en isolant les effets des macros et en permettant des générations évolutives. Cette fonctionnalité permet aux utilisateurs du langage de définir une limite d’encapsulation. Il existait jusque-là trois fonctionnalités de ce type qui permettent aux développeurs de créer leurs propres mots de pouvoir en (a) donnant un nom défini par l'utilisateur en (b) quelque chose dont l'implémentation est cachée, explique Sutter. Ce sont : la variable (qui encapsule la valeur actuelle), la fonction (qui encapsule le code et le comportement) et la classe (qui encapsule les deux pour délivrer un ensemble d’états et de fonctions).
Même des fonctionnalités majeures telles que les Modèles constituent des moyens de décorer ou de paramétrer ces trois fonctionnalités fondamentales. À ces trois, est ajoutée maintenant une quatrième, les Modules qui encapsulent les trois pour en livrer un ensemble. Les Coroutines quant à elles, sont des fonctions qui peuvent suspendre et reprendre leur exécution tout en conservant leur état. L'évolution en C++ 20 va encore plus loin. Le terme Coroutines est inventé par Melvin Conway. Il l'a utilisé dans sa publication pour la construction d'un compilateur en 1963. Cette fonctionnalité existe également dans les langages comme Python. L'implémentation spécifique de Coroutines en C++ est un peu intéressante. Au niveau le plus élémentaire, il ajoute quelques mots-clés à C++ comme co_return, co_await, co_yield ainsi que des types de bibliothèques qui fonctionnent avec eux. Une fonction devient une coroutine en ayant une de ces fonctions dans son corps.
std::format
std::format ajoute la prise en charge des chaînes de format à la bibliothèque standard C++, y compris pour les paramètres de type sécurisé et de position. Si vous connaissez les chaînes au format Boost.Format ou POSIX, ou même simplement printf, vous saurez exactement de quoi il s'agit. Selon lui, std::format donne le meilleur de printf (commodité) et le meilleur de iostreams (sécurité et extensibilité des iostreams), mais il ne se limite pas à iostreams. Il vous permet également de formater n’importe quelle chaîne. « Cela fait longtemps que j'attends cela, de sorte que je n'aurai plus jamais à utiliser l’entête iomanip », a-t-il déclaré à propos.
Les conteneurs constexpr
Les conteneurs constexpr suivants ont été ajoutés à la norme C++ 20 : constexpr INVOKE, constexpr std::vector et constexpr std::string. Selon Sutter, cela signifie que beaucoup de code C++ ordinaire peut être exécuté à la compilation, y compris même les conteneurs std::vector et chaînes dynamiques standard. « C’était quelque chose qui aurait été difficile à imaginer il y a quelques années à peine, mais cela montre de plus en plus que nous sommes sur un chemin où nous pouvons exécuter du code C ++ simple au moment de la compilation au lieu d’essayer d’exprimer ces calculs sous forme de métaprogrammes de modèle », a-t-il précisé à propos de ces ajouts et constexpr std::string.
Au cours de cette réunion, le comité a également adopté un plan pour C ++ 23, qui inclut la hiérarchisation d'une bibliothèque standard modulaire, le support de bibliothèque pour les coroutines, les exécuteurs et la mise en réseau. Elle est prévue à Varna (en Bulgarie).
Évolution du langage
Evolution Working Group Incubator (EWGI) Progress
L'incubateur EWG s'est réuni pendant trois jours à Prague et a examiné et commenté 22 articles pour C ++ 23. 10 de ces documents ont été transmis à Evolution, éventuellement avec quelques révisions demandées. Notamment:
- Élision de copie garantie pour les objets de retour nommés
- Déclaration et utilisation généralisées de pack
- Modèles de membres pour les classes locales
Plusieurs articles ont reçu beaucoup de commentaires et reviendront à l'incubateur, probablement à Varna:
- Un opérateur pipeline-rewrite
- Des paramètres template universels
- Captures lambda partiellement mutables
- C ++ devrait prendre en charge la compilation just-in-time
Concernant les paramètres template universels, imaginez-vous essayer d'écrire une métafonction pour apply :
Code C++ : | Sélectionner tout |
1 2 3 4 5 | template <template <class...> class F, typename... Args> using apply = F<Args...>; template <typename X> class G { using type = X; }; static_assert(std::is_same<apply<G, int>, G<int>>{});// OK |
Dès que G essaie de prendre n'importe quel type de NTTP (paramètre de template non-type) ou un paramètre de template-template, apply devient impossible à écrire; nous devons fournir des types de paramètres analogues pour chaque combinaison de paramètres possible:
Code C++ : | Sélectionner tout |
1 2 3 | template <template <class> class F> using H = F<int>; apply<H, G>// error, can't pass H as arg1 of apply, and G as arg2 |
La solution proposée ? Un moyen de spécifier un paramètre template vraiment universel qui peut se lier à tout ce qui peut être utilisé comme argument template. Appelons le template auto. « La syntaxe est la meilleure que nous puissions trouver; mais il existe de nombreuses façons inexplorées d'orthographier un tel paramètre template ». Par exemple :
Code C++ : | Sélectionner tout |
1 2 3 4 5 | template <template <template auto...> class F, template auto... Args> using apply = F<Args...>; apply<G, int>;// OK, G<int> apply<H, G>;// OK, G<int> |
Le nouveau paramètre template universel introduit des généralisations similaires à l'universel auto NTTP ; afin de permettre le pattern-matching sur le paramètre, les classes template doivent également pouvoir être spécialisées sur le type de paramètre:
Code C++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | template <template auto> struct X; template <typename T> struct X<T> { // T is a type using type = T; }; template <auto val> struct X<val> : std::integral_constant<decltype(val), val> { // val is an NTTP }; template <template <class> F> struct X<C> { // C is a unary metafunction template <typename T> using func = F<T>; }; |
Source : Rapport du comité C++