51 votes

Quelles alternatives sérieuses existent pour la bibliothèque IOStream? (à part cstdio)

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é.

8voto

smoothware Points 585

La bibliothèque {fmt} : Je viens de tomber dessus via une conférence YouTube et elle semble être assez sympa.

Un dispositif de formatage basé sur {fmt} a été proposé pour la normalisation en C++20 : P0645. Tant P0645 que {fmt} utilisent une syntaxe de chaîne de format similaire à celle de Python qui est proche de celle de printf mais utilise {} comme délimiteurs au lieu de %.

Par exemple

#include 

int main() {
  fmt::print("La réponse est {}.", 42);
}

affiche "La réponse est 42." sur stdout.

La fonction std::format proposée pour C++20 :

#include 

int main() {
  std::string s = std::format("La réponse est {}.", 42);
}

Caractéristiques notables de {fmt} :

  1. Type et sécurité de la mémoire avec les erreurs dans les chaînes de format optionnellement rapportées au moment de la compilation.

  2. Extensibilité : les utilisateurs peuvent écrire des formateurs pour leurs types, y compris des analyseurs spécifiques de format personnalisés (comme en Python).

  3. Code binaire compact. L'exemple d'impression ci-dessus se compile en :

    main: # @main
      sub rsp, 24
      mov qword ptr [rsp], 42
      mov rcx, rsp
      mov edi, offset .L.str
      mov esi, 17
      mov edx, 2
      call fmt::v5::vprint(fmt::v5::basic_string_view, fmt::v5::format_args)
      xor eax, eax
      add rsp, 24
      ret
    .L.str:
      .asciz "La réponse est {}."

    ce qui est comparable à printf et bien meilleur que les flux d'entrée/sortie.

  4. Performance : {fmt} est considérablement plus rapide que les implémentations courantes de printf et iostreams. Voici les résultats d'un banc d'essai tinyformat sur macOS avec clang :

    ================= ============= ===========
    Bibliothèque      Méthode        Temps d'exécution, s
    ================= ============= ===========
    libc              printf          1.01
    libc++            std::ostream    3.04
    {fmt} 1632f72     fmt::print      0.86
    tinyformat 2.0.1  tfm::printf     3.23
    Boost Format 1.67 boost::format   7.98
    Folly Format      folly::format   2.23
    ================= ============= ===========

7voto

ildjarn Points 38377

Boost.Spirit.Qi pour l'entrée, Boost.Spirit.Karma pour la sortie. Peut lire/écrire sur tout ce qui peut être représenté comme une plage d'itérateurs.

3 votes

J'aime ces deux bibliothèques - je ne pense pas qu'elles puissent être des remplacements généraux pour iostream car 1. elles ont toutes deux des temps de compilation horriblement longs comparés aux bibliothèques traditionnelles, et 2. bonne chance pour déboguer les messages d'erreur que vous obtenez en cas d'erreur de syntaxe. Néanmoins, une réponse raisonnable à ma question initiale, donc +1.

15 votes

Les flux étaient trop compliqués selon l'OP, donc maintenant nous utilisons Boost Spirit? Maintenant nous avons deux problèmes!

1 votes

@John : Selon ce que je comprends, l'OP voulait dire compliqué en termes de facilité d'extension et de complexité/surcharge d'exécution. À cet égard, Boost.Spirit est inégalé, donc je maintiens cette réponse.

6voto

iammilind Points 29275

Vous pourriez être intéressé par la bibliothèque Fast Format. Vous pouvez voir la comparaison sur leur site web avec diverses autres bibliothèques également.

1 votes

Wow.. cela a l'air vraiment génial. Il faudra jouer et voir comment les choses se passent avec ça.

1 votes

Malheureusement, le site web ne semble pas fonctionner et il nécessite STLPort qui ne semble pas être en très bon état.

1 votes

Je ne coche pas cela pour le moment en raison de la dépendance à STLPort (ce qui m'a empêché de l'utiliser à l'époque) - je reviendrai probablement vérifier plus tard, mais je veux d'abord acquérir davantage d'expérience avec la bibliothèque. (Le manque de maintenance récemment n'est cependant pas un bon signe)

0voto

Dark_CPP Points 1

Que diriez-vous d'utiliser la bibliothèque fmt et la bibliothèque scn, fmt gère très bien la sortie et scn peut gérer les entrées. J'ai utilisé ces deux bibliothèques en même temps et c'est beaucoup moins douloureux à utiliser que la norme (et c'est lisible!).

Vous devriez les essayer tous les deux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X