Je suis à la recherche d'une bibliothèque qui fonctionne de manière similaire à iostreams, dans le sens où elle effectue des conversions et permet l'écriture dans des tampons mémoire, des fichiers et la console. Cependant, j'aimerais quelque chose de sûr en termes de type, comme iostream. Y a-t-il des bibliothèques sérieuses qui font cela?
Pouvoir spécifier l'encodage de sortie pour les éléments serait un plus.
Remarque: Je ne suis pas intéressé par les bibliothèques qui se contentent de front-end iostreams car elles ajoutent simplement plus de complexité à ce que fait iostreams, par exemple boost::format
.
Réponse Préemptive aux commentaires : Je ne veux pas utiliser cstdio car avec ce système, il est impossible de rendre le code indifférent à l'emplacement de sortie. Autrement dit, vous devez appeler une fonction pour envoyer des éléments vers des tampons, et vous devez en appeler une autre pour les envoyer vers des fichiers, et encore une autre pour la console, etc.
MODIFICATION2 : En réponse à l'avalanche de commentaires ci-dessous : j'en ai assez à la fois d'iostreams et de cstdio. Voici des raisons plus spécifiques. J'ai essayé de garder ma "plainte" hors de cette question, mais les gens continuent de me demander si je suis fou, alors voici ma logique.
cstdio
- Impossible de gérer correctement les caractères Unicode
- Impossible d'écrire dans quelque chose comme une chaîne sans gestion manuelle du tampon
- Requiert souvent le support d'extensions non standard (par exemple,
vsnprintf
) pour être utilisable (MODIFICATION: Bon, la bibliothèque standard de C99 étant en C++11 ajoute la plupart ou la totalité de ces éléments maintenant) - Impossible de changer l'emplacement de sortie sans changer le code original (des extensions non standard comme dans glibc permettent de traiter un pointeur de fichier comme un tampon, ce qui fait cela... mais c'est toujours simplement cela, une extension non standard)
- Rend la sécurité "amusante" (au point où des chapitres entiers sont dédiés dans des documents de sécurité expliquant des problèmes, par exemple avec les chaînes de format de "printf" et ainsi de suite)
- Pas sûr en termes de type
iostreams
- Lent
- Trop compliqué pour un client. Si vous n'utilisez que ce que la bibliothèque standard propose, c'est super, mais tenter d'étendre les choses est presque impossible. J'ai lu le livre entier "Standard C++ IOStreams and Locales" -- le seul livre apparemment disponible sur le sujet -- deux fois -- et je ne comprends toujours pas ce qui se passe.
J'adore iostreams en concept, même l'utilisation de operator<<
que certaines personnes semblent ne pas aimer, mais cela me semble beaucoup trop sur-ingeniéré. Une personne ne devrait pas avoir à passer d'innombrables heures à lire des livres pour être un simple client de votre bibliothèque. Bien sûr, si vous ajoutez une nouvelle source de sortie ou quelque chose du genre, je pourrais comprendre, mais.... les clients devraient être protégés de cette complexité. (N'est-ce pas le rôle d'une bibliothèque?)
C'est à peu près la seule chose douloureuse en C++ qui "fonctionne simplement" dans d'autres langages de programmation, que je ne vois aucune raison de compliquer.
0 votes
"et parce que l'écriture de votre propre
operator<<
est... une tâche intéressante à faire correctement" - comment cela ?13 votes
Les raisons de performance sont souvent exagérées - en fait, j'ai découvert que sur les implémentations récentes iostream peut surpasser stdio. D'autre part, je suis d'accord que iostream n'est pas très bien conçu, et une alternative plus agréable vaudrait la peine d'être considérée.
7 votes
@Xeo: Vous devez sauvegarder l'état du flux, utiliser ces choses "sentry" pour gérer les erreurs, vérifier les spécificateurs d'exception pour déterminer s'il faut ou non renvoyer, restaurer l'état du flux quoi qu'il arrive, etc. Je ne veux pas toute cette complexité.
0 votes
Certaines personnes ont trop de temps libre entre les mains. :-)
0 votes
@pax: Je suis confus. Que voulez-vous dire?
0 votes
@Billy: N'était-il pas nécessaire d'utiliser
sentry
uniquement si vous manipuliez directement lestreambuf
?0 votes
@Billy: Restaurez l'état -> RAII, et pourriez-vous donner un exemple (ideone?) d'une surcharge "compliquée" de
operator<<
?1 votes
@Matteo: Pour être honnête, je ne sais pas. Cependant, plus je regarde cela, plus je pense que "c'est une façon incroyablement compliquée de gérer essentiellement ce qui est ToString dans d'autres langues".
0 votes
@Xeo : Je n'ai aucun exemple. Je n'ai jamais vu personne essayer de le faire correctement, cependant. Je vois beaucoup de tentatives pour le faire correctement, mais peu semblent gérer les erreurs correctement ou restaurer l'état du flux correctement.
0 votes
@Billy : pour être honnête, en fait je n'ai jamais compris la moitié des classes impliquées dans iostream,
sentry
incluse. :) Et j'ai entendu de nombreuses personnes dire que, même s'ils ont été conçus pour offrir de la flexibilité, ils échouent même à cela dans presque tous les scénarios du monde réel.0 votes
Au fait, je connais la bibliothèque Boost.Iostreams, mais je ne l'ai jamais vraiment examinée, est-ce que quelqu'un sait si elle est aussi bonne pour les entrées/sorties de fichiers "normales" ?
0 votes
operateur>>
était toujours là où j'ai toujours senti que la complexité devenait incontrôlable. Donc cela ne me dérange pas la partie o des flux d'entrée-sortie, mais un nouveau i serait génial.6 votes
+1 Bonne question, et je doute que vous allez obtenir une bonne réponse. Rien qui ne vous apportera du repos, de toute façon.
2 votes
@Matteo pour ce que j'en comprends, boost.iostreams définit des concepts pour les flux standard, afin de faciliter leur extension. Mais je ne pense pas qu'ils résolvent le problème de l'enfer de l'entrée formatée et de la sortie formatée.
1 votes
@Billy : Premièrement, créer un objet de garde d'état de flux est un code en une ligne, et si ta façon de vérifier les exceptions et de les jeter n'est pas bonne, tu peux envisager une option avec des macros. Deuxièmement, avec la version "v" des fonctions de la famille printf/scanf, tu peux facilement créer une fonction d'enrobage unique qui gérera diverses cibles de sortie. Cela dit, aucune des options n'est excellente. J'ai vu beaucoup d'entreprises avec des classes "fast_xstream" maison, mais aucune dans les bibliothèques Open Source, et aucune n'était plus complète ou mieux conçue que `
iostream
` de toute façon - juste un peu plus rapide pour avoir réduit la fonctionnalité.0 votes
@Tony: Le problème avec la version "v" de ces fonctions est qu'elles ne sont pas standard, donc je ne peux pas me fier à elles.
0 votes
@Tony: Comment exactement la création d'un objet de garde d'état en une seule ligne? Ce n'est certainement pas dans la bibliothèque standard. Je sais que Boost a quelque chose qui le fera mais je pense que c'est un peu fou de devoir utiliser une bibliothèque tierce importante pour utiliser correctement les flux d'entrée/sortie.
0 votes
@Billy : D'après une page de manuel : "... les fonctions vprintf(), vfprintf() et vsprintf() sont conformes à ANSI X3.159-1989 (
ANSI C89'') et à ISO/IEC 9899:1999 (
ISO C99''). ... les fonctions snprintf() et vsnprintf() sont conformes à ISO/IEC 9899:1999 (``ISO C99'')." Pas suffisant ?0 votes
+1 question intéressante, car je me posais récemment la même question... bien sûr, pour moi, cela équivaut à envisager d'écrire ma propre alternative, que ce soit vraiment une bonne idée ou non.
0 votes
@Tony: Oui, ce n'est pas suffisant. C99 != C++. C++ ne comprend pas toutes les fonctionnalités de C99 - y compris ces fonctions. Je ne crois pas qu'elles soient ajoutées dans C++0x non plus.
1 votes
@Billy : vous créez une classe qui préserve l'état du flux passé au constructeur et le restaure lors de sa destruction. Donc, 10 lignes pour la classe, 1 ligne par utilisation. Pas besoin d'utiliser boost pour quelque chose d'aussi trivial.
0 votes
@John: J'ai presque envisagé d'écrire quelque chose comme ça; malheureusement, je n'ai pas le temps de le faire. J'espérais qu'il existait déjà quelque chose qui le ferait.
0 votes
@Tony: Le problème principal avec vsnprintf (qui est vraiment la fonction que vous seriez coincé en utilisant) est qu'elle ne supporte pas correctement les caractères larges, de ce que je me souviens. (La prise en charge de l'unicode n'est pas une option aujourd'hui) En ce qui concerne l'objet "écrire votre propre sauvegardateur d'état" - je suppose que c'est possible de le faire. D'accord, maintenant vous avez la gestion des erreurs, la largeur du champ de format et les problèmes de
sentry
à gérer par-dessus tout ça... cela semble bien trop compliqué pour une opération qui devrait être simple.0 votes
@Billy vous n'avez pas besoin de maintenir l'état du flux dans une entrée formatée. Si l'entrée échoue, laissez le flux dans un état échoué. Pas besoin de restaurer quoi que ce soit.
1 votes
@wilhelmtell:
boost::format
ajoute essentiellement une enveloppe autour des iostreams - il utilise toujours les surcharges d'operator<<
pour écrire les choses. Il a les mêmes faiblesses que les iostreams eux-mêmes (lent, compliqué). Je pense que c'est une excellente bibliothèque, mais ce n'est pas exactement ce que je recherche ici.0 votes
@Billy oui oui, tu as raison, j'y ai pensé un instant après avoir posté mon commentaire. :-S vois mon autre commentaire ci-dessus cependant : tu n'as pas toujours besoin de maintenir l'état d'erreur, pas dans une saisie formatée.
0 votes
@wilhelmtell : c'est la précision, l'état dec/hex, etc. qui est bon à pousser/pop lorsque le flux fonctionne...
1 votes
Etes-vous sûr que C++ est le langage qui vous convient ?
4 votes
@jeffamaphone : Oui. J'aime tout le reste -- c'est cette bibliothèque en particulier que je n'aime pas. Le C++ est compliqué car il est puissant -- les bibliothèques FORMIDABLES comme la STL montrent cependant que la complication en vaut la peine. La complexité est justifiée lorsqu'elle entraîne de la flexibilité ; mais les implémentations de flux d'autres langues sont bien plus simples, tout en étant tout aussi flexibles. (Pour être honnête, les flux en C++ datent de presque tout le monde d'autre)
1 votes
Avez-vous déjà trouvé une solution à ce problème?
1 votes
@Shafik: Non. Toujours aussi pénible.