Nous avons vu dans la Section 8.12 un exemple d'application des classes de flux d'entrée / sortie de la bibliothèque pour les entrées / sorties standards des programmes. En réalité, ces classes de gestion des flux s'intègrent dans une hiérarchie complexe de classes permettant de manipuler les flux d'entrée / sortie et pas seulement pour les entrées / sorties standards.
En effet, afin de faciliter la manipulation des flux d'entrée / sortie, la bibliothèque standard C++ fournit tout un ensemble de classes template. Ces classes sont paramétrées par le type de base des caractères qu'elles manipulent. Bien entendu, les types de caractères les plus utilisés sont les type char et wchar_t, mais il est possible d'utiliser a priori n'importe quel autre type de donnée pour lequel une classe de traits char_traits est définie.
Ce chapitre a pour but de détailler cette hiérarchie de classes. Les principes de base et l'architecture générale des flux C++ seront donc abordés dans un premier temps, puis les classes de gestion des tampons seront traitées. Les classes génériques de gestion des flux d'entrée / sortie seront ensuite décrites, et ce sera enfin le tour des classes de gestion des flux orientés chaînes de caractères et des classes de gestion des flux orientés fichiers.

Programmation C-C++/La bibliothèque standard/Les locales

Il existe de nombreux alphabets et de nombreuses manières d'écrire les nombres, les dates et les montants de part le monde. Chaque pays, chaque culture dispose en effet de ses propres conventions et de ses propres règles, et ce dans de nombreux domaines. Par exemple, les Anglo-saxons ont pour coutume d'utiliser le point (caractère '.') pour séparer les unités de la virgule lorsqu'ils écrivent des nombres à virgule et d'utiliser une virgule (caractère ',') entre chaque groupe de trois chiffres pour séparer les milliers des millions, les millions des milliards, etc. En France, c'est la virgule est utilisée pour séparer les unités de la partie fractionnaire des nombres à virgule, et le séparateur des milliers est simplement un espace. De même, ils ont l'habitude d'écrire les dates en mettant le mois avant les jours, alors que les Français font l'inverse.
Il va de soi que ce genre de différences rend techniquement très difficile l'internationalisation des programmes. Une solution est tout simplement de dire que les programmes travaillent dans une langue « neutre », ce qui en pratique revient souvent à dire l'anglais puisque c'est la langue historiquement la plus utilisée en informatique. Hélas, si cela convenait parfaitement aux programmeurs, ce ne serait certainement pas le cas des utilisateurs ! Il faut donc, à un moment donné ou à un autre, que les programmes prennent en compte les conventions locales de chaque pays ou de chaque peuple.
Ces conventions sont extrêmement nombreuses et portent sur des domaines aussi divers et variés que la manière d'écrire les nombres, les dates ou de coder les caractères et de classer les mots dans un dictionnaire. En informatique, il est courant d'appeler l'ensemble des conventions d'un pays la locale de ce pays. Les programmes qui prennent en compte la locale sont donc dits localisés et sont capables de s'adapter aux préférences nationales de l'utilisateur.
Si la traduction de tous les messages d'un programme ne peut pas être réalisée automatiquement, il est toutefois possible de prendre en compte les locales relativement facilement. En effet, les fonctionnalités des bibliothèques C et C++, en particulier les fonctionnalités d'entrée / sortie, peuvent généralement être paramétrées par la locale de l'utilisateur. La gestion des locales est donc complètement prise en charge par ces bibliothèques et un même programme peut donc être utilisé sans modification dans divers pays.
La gestion des locales en C++ se fait par l'intermédiaire d'une classe générale, la classe locale, qui permet de stocker tous les paramètres locaux des pays. Cette classe est bien entendu utilisée par les flux d'entrée / sortie de la bibliothèque standard, ce qui fait que vous n'aurez généralement qu'à initialiser cette classe au début de vos programmes pour leur faire prendre en compte les locales. Cependant, il se peut que vous ayez à manipuler vous-même des locales ou à définir de nouvelles conventions nationales, surtout si vous écrivez des surcharges des opérateurs de formatage des flux operator« et operator». Ce chapitre présente donc les notions générales des locales, les différentes classes mises en œuvre au sein d'une même locale pour prendre en charge tous les aspects de la localisation, et la manière de définir ou de redéfinir un de ces aspects afin de compléter une locale existante.

Programmation C-C++/La bibliothèque standard/Les conteneurs

La plupart des programmes informatiques doivent, à un moment donné ou à un autre, conserver un nombre arbitraire de données en mémoire, généralement pour y accéder ultérieurement et leur appliquer des traitements spécifiques. En général, les structures de données utilisées sont toujours manipulées par des algorithmes classiques, que l'on retrouve donc souvent, si ce n'est plusieurs fois, dans chaque programme. Ces structures de données sont communément appelées des conteneurs en raison de leur capacité à contenir d'autres objets.
Afin d'éviter aux programmeurs de réinventer systématiquement la roue et de reprogrammer les structures de données et leurs algorithmes associés les plus classiques, la bibliothèque standard définit un certain nombre de classes template pour les conteneurs les plus courants. Ces classes sont paramétrées par le type des données des conteneurs et peuvent donc être utilisées virtuellement pour toutes les situations qui se présentent.
Les conteneurs de la bibliothèque standard ne sont pas définis par les algorithmes qu'ils utilisent, mais plutôt par l'interface qui peut être utilisée par les programmes clients. La bibliothèque standard impose également des contraintes de performances sur ces interfaces en termes de complexité. En réalité, ces contraintes sont tout simplement les plus fortes qui soient, ce qui garantit aux programmes qui les utilisent qu'ils auront les meilleures performances possibles.
La bibliothèque classifie les conteneurs en deux grandes catégories selon leurs fonctionnalités : les séquences et les conteneurs associatifs. Une séquence est un conteneur capable de stocker ses éléments de manière séquentielle, les uns à la suite des autres. Les éléments sont donc parfaitement identifiés par leur position dans la séquence, et leur ordre relatif est donc important. Les conteneurs associatifs, en revanche, manipulent leurs données au moyen de valeurs qui les identifient indirectement. Ces identifiants sont appelées des clefs par analogie avec la terminologie utilisée dans les bases de données. L'ordre relatif des éléments dans le conteneur est laissé dans ce cas à la libre discrétion de ce dernier et leur recherche se fait donc, généralement, par l'intermédiaire de leurs clefs.
La bibliothèque fournit plusieurs conteneurs de chaque type. Chacun a ses avantages et ses inconvénients. Comme il n'existe pas de structure de données parfaite qui permette d'obtenir les meilleures performances sur l'ensemble des opérations réalisables, l'utilisateur des conteneurs de la bibliothèque standard devra effectuer son choix en fonction de l'utilisation qu'il désire en faire. Par exemple, certains conteneurs sont plus adaptés à la recherche d'éléments mais sont relativement coûteux pour les opérations d'insertion ou de suppression, alors que pour d'autres conteneurs, c'est exactement l'inverse. Le choix des conteneurs à utiliser sera donc déterminant quant aux performances finales des programmes.

Programmation C-C++/La bibliothèque standard/Les algorithmes