Issu du streambuf sans réécriture d'un flux correspondant
Question
Il y a quelques jours, j'ai décidé que ce serait amusant d'écrire une sous-classe de streambuf
qui utiliserait mmap
et en lecture.
Je regardais comment mon STL (SGI) mis en œuvre filebuf
et réalisé que basic_filebuf
contient un FILE*
. Donc, héritant de basic_filebuf
est hors de question.
Je hérité de basic_streambuf
. Alors je voulais lier mon mmapbuf
à un fstream.
Je pensais que la seule chose que je dois faire serait de copier l'interface implicite de filebuf
... mais qui était une erreur évidente. Dans le SGI, basic_fstream
est propriétaire d'un basic_filebuf
. Peu importe si je l'appelle basic_filestream.std::::ios::rdbuf( streambuf* )
, le filestream ignore complètement et utilise son propre filebuf
.
Alors maintenant, je suis un peu confus ... Bien sûr, je peux créer mon propre mmfstream
, ce serait la copie exacte / coller du fstream
mais que
Ce que je ne comprends pas, est: pourquoi fstream
est si étroitement lié à filebuf
, de sorte qu'il est impossible d'utiliser quoi que ce soit d'autre qu'un filebuf
Le point entier de séparation des flux et bufs est que l'on peut utiliser un jet avec un tampon différent.
Solutions:
=> filestream
doit compter sur l'interface implicite de filebuf
. Autrement dit, fstream devrait être templated par une classe de streambuf. Cela permettrait à chacun de fournir sa propre sous-classe de streambuf à un fstream
tant qu'il implémente l'interface implicite de filebuf
. Problème:. Nous ne pouvons pas ajouter un paramètre de modèle à fstream
car il casserait sélecteurs de modèle en utilisant fstream
comme paramètre de modèle de modèle
=> filebuf
doit être une classe virtuelle pure sans attributs supplémentaires. Alors que l'on peut hériter de sans porter tout son fichier * ordures.
Vos idées sur le sujet?
La solution
Consultez mapped_file dans le Boost.Iostreams bibliothèque. Je ne l'ai jamais utilisé utilisé moi-même, mais il semble que cela pourrait déjà faire ce que vous avez besoin.
EDIT: Oops, relisez vos questions et je vois que vous faites cela pour le plaisir. Peut-être que vous pouvez inspirer de Boost.Iostreams?
Autres conseils
dans les flux d'entrées-sorties de la conception, la plupart des courants réels de la fonctionnalité (par opposition à la fonctionnalité de tampons de flux) est mis en oeuvre dans std::basic_istream
, std::basic_ostream
, et de leurs classes de base. Les classes de flux de chaîne et le fichier sont plus ou moins que des emballages de commodité qui font en sorte un cours d'eau avec le type de tampon est instancié .
Si vous souhaitez étendre les cours d'eau, vous presque toujours envie de donner votre propre classe tampon de flux , et vous avez besoin presque jamais de fournir votre propre classe de flux. .
Une fois que vous avez votre propre type de mémoire tampon de flux, vous pouvez alors faire le tampon pour tout objet de flux que vous arrive d'avoir autour. Ou vous dérivez vos propres classes de std::basic_istream
, std::basic_ostream
et std::basic_iostream
qui instancie votre mémoire tampon de flux et de le transmettre à leurs classes de base.
Ce dernier est plus pratique pour les utilisateurs, mais vous oblige à écrire du code-plaque de la chaudière pour le instanciation de la mémoire tampon (à savoir les constructeurs pour la classe de flux).
Pour répondre à votre question: flux de fichiers et tampon sont accouplées si étroitement que l'ancien existe seulement pour faciliter la création de ce dernier. L'utilisation d'un flux de fichiers, il est facile de mettre tout en place.
En utilisant votre propre classe de flux pour envelopper la construction de votre propre tampon de flux ne devrait pas être un problème, puisque vous ne devriez pas passer autour des flux fichier de toute façon, mais seulement (références) aux classes de base.
fstream
est pas en soi une grande classe. Il hérite de basic_stream
de fournir un soutien pour toutes les opérations de <<
et >>
, contient une steambuf
spécialisée qui doivent être initialisé, et les constructeurs correspondant à transmettre les paramètres au constructeur de streambuf
.
Dans un sens, ce que vous avez écrit sur votre solution est basé sur un modèle OK. Mais basic_stream
peut également être dérivé en tcp_stream
par exemple. Dans ce cas, les constructeurs de fstream
sont un peu inutile. Ainsi, vous devez fournir une nouvelle classe de tcpstream
, héritant de basic_stream
avec les bons paramètres pour les constructeurs pour pouvoir créer le tcp_stream
. En fin de compte, vous n'utiliser quoi que ce soit de fstream
. La création de ce nouveau tcpstream
est une question d'écrire 3 ou 4 fonctions seulement.
En fin de compte, vous dériverait de la classe fstream
sans aucune véritable raison. Cela ajouterait plus de couplage dans la hiérarchie des classes, couplage non nécessaire.
Le point entier de std::fstream
est qu'il est un _ F std::stream
à base _ile. Si vous voulez un std::stream
ordinaire soutenu par votre mmstreambuf
, vous devez créer un mmstreambuf
et le transmettre à std::stream::stream(std::streambuf*)