2023-08-22 16:13:00
La bibliothèque standard C++23 brille par des améliorations impressionnantes. Dans cet article, je parlerai de la bibliothèque standard modularisée et des deux fonctionnalités pratiques std::print
et std::println
écrire.
Publicité
Rainer Grimm travaille depuis de nombreuses années en tant qu’architecte logiciel, chef d’équipe et responsable de la formation. Il aime écrire des articles sur les langages de programmation C++, Python et Haskell, mais aime aussi intervenir fréquemment lors de conférences spécialisées. Sur son blog Modernes C++, il parle intensément de sa passion pour le C++.
Chaque défi de programmation dans un nouveau langage commence par le programme “Hello World”. Depuis C++98, ceci a été notre point de départ :
#include
int main() {
std::cout << "Hello Worldn";
}
Franchement, vous devez abandonner vos vieilles habitudes en C++23. Le programme « Hello World » ressemble désormais à ceci :
import std;
int main() {
std::println("Hello World");
}
Laissez-moi analyser le programme.
Publicité
Bibliothèque standard modularisée
C++23 prend en charge une bibliothèque standard modularisée. Avec la simple commande import std
; toute la bibliothèque standard est à votre disposition. Si vous aimez aussi les fonctions C globales printf
tu dois l'utiliser import std.compat;
utiliser. Voici le programme "Hello World" correspondant avec printf:
import std.compat;
int main() {
printf("Hello Worldn");
}
La bibliothèque standard modularisée apporte deux améliorations majeures : un temps de compilation et une convivialité considérablement améliorés.
Temps de compilation considérablement amélioré
L'import de la bibliothèque standard (import std
) est littéralement « gratuit ». Cela signifie que les temps de compilation sont considérablement réduits. Les premiers chiffres tirés de l'expérience indiquent que les temps de compilation sont réduits d'un facteur d'au moins 10. La raison de cette amélioration est évidente. Au lieu d'inclure successivement vos fichiers d'en-tête, vous importez un module. Il n’existe donc qu’un seul module contenant toute la bibliothèque standard C++23. Jusqu'à présent, seul le compilateur MSVC prend en charge cette bibliothèque standard modularisée : Tutoriel : Importer la bibliothèque standard C++ à l'aide de modules depuis la ligne de commande.
Convivialité améliorée
Supposons que vous souhaitiez la fonction std::accumulate
utiliser. Savez-vous quel fichier d'en-tête inclure ? Est-ce le fichier d'en-têtenumeric
>,functional
> oualgorithm
>? C'était peut-être trop facile pour toi. Comment ça va maintenant ? std::forward
ou pourquoi le programme suivant ne peut-il pas être compilé ?
int main() {
auto list = {1, 2, 3, 4};
}
L'expression {1, 2, 3, 4}
est un std::initializer_list
. Pour les utiliser, l'en-têteinitializer_list
> sont utilisés. Bien entendu, cet en-tête est inclus automatiquement lorsqu'un conteneur comme std::vector
est utilisé.
Comparez les exemples précédents avec un exemple simple import std;
ou import std::compat;.
D'après ma propre expérience, je sais que les débutants ne sont pas les seuls à échouer lorsqu'ils utilisent les bons fichiers d'en-tête.
Je ne sais pas si vous l'avez remarqué, mais mon programme C++23 "Hello World" utilisait une deuxième fonctionnalité de C++23 :
std::print
et std::println
C++23 propose deux surcharges pour les deux fonctions :
std::print
template< class... Args >
void print( std::FILE* stream,
std::format_string fmt, Args&&... args );
template< class... Args >
void print( std::format_string fmt, Args&&... args );
std::println
template< class... Args >
void println( std::FILE* stream,
std::format_string fmt, Args&&... args );
template< class... Args >
void println( std::format_string fmt, Args&&... args );
La première différence entre std::print
et std::println
est évident: std::println
ajoute un saut de ligne. Les points suivants sont encore plus intéressants :
Modèle variadique
std::print
et std::println
sont des modèles variadiques. Les modèles variadiques sont des modèles qui peuvent accepter n'importe quel nombre d'arguments. Vos arguments sont parfaitement transmis. std::print
et std::println
sont la variante de type sécurisé de printf
. À printf
vous devez spécifier la chaîne de format, à std::print
et std::println
vous utilisez des caractères génériques dans la chaîne de format. En général, le compilateur déduit le type de données pour les espaces réservés en suivant les règles de std::format
à partir de C++20 s'applique. ça semble logique std::print
et std::println
être en sucre syntaxique C++23 pour les chaînes de format en C++20. Voici le programme "Hello World" modifié en C++23 qui std::format
utilisé.
import std;
int main() {
// std::println("Hello World");
std::cout << std::format("{:}n", "Hello World");
}
Si vous souhaitez en savoir plus sur les modèles Variadic, Perfect Forwarding et std::forma
Je ne veux pas savoir, lis mes anciens articles :
Prise en charge Unicode
Que std::print
et std::println
en C++23 Syntactic Sugar pour les chaînes de format en C++20 n'est pas vrai. Parce que std::print
et std::println
prend en charge Unicode. Permettez-moi de vous citer la proposition P2093R14 :
Un autre problème est le formatage du texte Unicode :
std::cout << "Привет, κόσμος!";
Si le codage source et d'exécution est UTF-8, cela produira le résultat attendu sur la plupart des systèmes GNU/Linux et macOS. Malheureusement sous Windows, il est presque garanti de produire du mojibake malgré le fait que le système est entièrement capable d'imprimer du Unicode, par exemple
Привет κόσμος!
même lorsqu'il est compilé avec /utf-8 en utilisant Visual C++ ([MSVC-UTF8]). Cela se produit parce que le terminal assume dans ce cas la page de codes 437 indépendamment du codage d'exécution.
Avec le document proposé
std::print("Привет, κόσμος!");
imprimera "Привет, κόσμος!" comme prévu, permettant aux programmeurs d'écrire du texte Unicode de manière portable en utilisant des fonctionnalités standard.
Tout flux de sortie
Les deux types std::print
et std:println
avoir une surcharge qui accepte n’importe quel flux de sortie. Par défaut est le flux de sortie stdout
.
std::format
et par conséquent aussi std::print
et std::println
en C++23 ont encore plus à offrir. En C++23, vous pouvez formater un conteneur de bibliothèque de modèles standard.
Sortie formatée d'un conteneur
Le programme suivant montre comment vous pouvez générer directement un conteneur de la STL. Jusqu'à présent, aucun compilateur C++ ne prend en charge cette fonctionnalité. Seul le tout nouveau compilateur Clang avec le libc++
au lieu de libstdc++
permet d'utiliser cette fonction au moins partiellement. Dans une implémentation C++23 entièrement conforme, je pourrais std::println
au lieu de std::format
utiliser.
// formatVector.cpp
#include
#include
#include
#include
int main() {
std::vector myInts{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::cout << std::format("{:}n", myInts);
std::cout << std::format("{::+}n", myInts);
std::cout << std::format("{::02x}n", myInts);
std::cout << std::format("{::b}n", myInts);
std::cout << 'n';
std::vector myStrings{"Only", "for", "testing", "purpose"};
std::cout << std::format("{:}n", myStrings);
std::cout << std::format("{::.3}n", myStrings);
}
J'en utilise un dans cet exemple std::vector
et une std::vector
. Si {:}
est utilisé comme espace réservé, les deux conteneurs (lignes 1 et 2) sont affichés directement. Devenez deux deux-points {::}
utilisés dans l'espace réservé, les éléments du std::vector
format. Le spécificateur de format suit le deuxième deux-points.
std::vector
: Les éléments du vecteur ont un signe +{::+}
sont hexadécimaux à 2 caractères avec le 0 comme caractère de remplissage{::02x}
alignés et sont représentés en binaire{::b}
.std::vector
: Chaque chaîne est tronquée à ses 3 premiers caractères :{::.3}
.
La capture d'écran suivante montre la sortie du programme dans Explorateur du compilateur:
Et après?
Dans mon prochain article sur la bibliothèque standard améliorée en C++23, j'utiliserai l'interface étendue de std::optional
et le nouveau type de données std::expected
présent pour la gestion des erreurs.
(carte)
#C23 #Une #bibliothèque #standard #modularisée #deux #nouvelles #fonctions
1692749412