Pregunta

Hace algunos días, decidí que sería divertido escribir un streambuf subclase que usaría mmap y leer. Miré cómo se implementó mi STL (SGI) filebuf y me di cuenta de que basic_filebuf contiene una FILE*. Así que heredando de basic_filebuf está fuera de discusión.

Entonces heredé de basic_streambuf. Entonces quería atar a mi mmapbuf a un fstream.

Pensé que lo único que tendría que hacer sería copiar la interfaz implícita de filebuf... Pero ese fue un claro error. En el SGI, basic_fstream posee un basic_filebuf. No importa si llamo basic_filestream.std::::ios::rdbuf( streambuf* ), el FileStream lo ignora por completo y usa su propio filebuf.

Así que ahora estoy un poco confundido ... Claro, puedo crear el mío mmfstream, esa sería la copia/pegar exacta del fstream Pero eso suena realmente no orientado a seco.

Lo que no puedo entender es: por que fstream está tan bien junto con filebuf, para que no sea posible usar nada más que un filebuf? El punto completo de separar corrientes y BUF es que se puede usar una transmisión con un búfer diferente.

Soluciones:

=> filestream debe confiar en la interfaz implícita de filebuf. Es decir, Fstream debe ser plantado por una clase StreamBuf. Eso permitiría a todos proporcionar su propia subclase StreamBuf a un fstream Mientras se implementa filebufLa interfaz implícita. Problema: no podemos agregar un parámetro de plantilla a fstream ya que rompería los selectores de plantilla mientras usa fstream Como parámetro de plantilla de plantilla.

=> filebuf Debe ser una clase virtual pura sin ningún atributo adicional. Para que uno pueda heredar de él sin llevar todo su archivo* basura.

Tus ideas sobre el tema?

¿Fue útil?

Solución

Verificar Mapped_file en el Boost.iostreams biblioteca. Nunca lo he usado yo mismo, pero parece que ya podría hacer lo que necesitas.

EDITAR: Vaya, vuelva a leer sus preguntas y veo que está haciendo esto por diversión. ¿Quizás puedas inspirarte en Boost.iostreams?

Otros consejos

En el diseño de las transmisiones de IO, la mayor parte de la funcionalidad de las transmisiones reales (a diferencia de la funcionalidad de los buffers de flujo) se implementa en std::basic_istream, std::basic_ostream, y sus clases base. Las clases de transmisión de cadenas y archivos son más o menos solo envolturas de conveniencia, lo que se asegura de que se instancia una secuencia con el tipo correcto de búfer.

Si quieres extender las transmisiones, Casi siempre quieres proporcionar tu Clase de búfer de transmisión propia, y casi nunca necesitas proporcionar tu propia clase de transmisión. .

Una vez que tenga su propio tipo de búfer de transmisión, puede convertirlo en el búfer para cualquier objeto de transmisión que tenga. O deriva sus propias clases de std::basic_istream, std::basic_ostream, y std::basic_iostream lo que instancia su búfer de transmisión y pasarlo a sus clases base.
Este último es más conveniente para los usuarios, pero requiere que escriba algún código de placa de caldera para la instanciación del búfer (es decir, constructores para la clase de flujo).

Para responder a su pregunta: las transmisiones de archivos y el búfer de archivos se acoplan tan estrechamente porque el primero solo existe para aliviar la creación de la segunda. El uso de una transmisión de archivo facilita la configuración de todo.
Usar su propia clase de transmisión para envolver la construcción de su propio búfer de transmisión no debería ser un problema, ya que no debería pasar las transmisiones de archivos de todos modos, sino solo (referencias) a las clases base.

fstream En sí mismo no es una gran clase. Hereda de basic_stream para proporcionar apoyo a todos los << y >> operaciones, contiene un especializado steambuf que deben inicializarse y los constructores correspondientes para pasar los parámetros al streambuf constructor.

En cierto sentido, lo que escribió sobre su solución templada está bien. Pero basic_stream También se puede derivar en un tcp_stream por ejemplo. En ese caso, los constructores de fstream son un poco inútiles. Por lo tanto, necesita proporcionar un nuevo tcpstream clase, heredando de basic_stream con los parámetros correctos para que los constructores puedan crear el tcp_stream. Al final, no usarías nada de fstream. Creando este nuevo tcpstream es cuestión de escribir 3 o 4 funciones solamente.

Al final, derivarías del fstream clase sin ninguna razón real. Esto agregaría más acoplamiento en la jerarquía de clase, acoplamiento innecesario.

El objetivo de std::fstream es que es un _F_ILE basado en std::stream. Si quieres un ordinario std::stream respaldado por tu mmstreambuf, entonces deberías crear un mmstreambuf y pasarlo a std::stream::stream(std::streambuf*)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top