Вытекает из StreamBuf, не переписывая соответствующий поток
Вопрос
Несколько дней назад я решил, что было бы весело написать streambuf
Подкласс, который использовал бы mmap
и читать. Я посмотрел, как реализован мой STL (SGI) filebuf
и понял это basic_filebuf
содержит FILE*
. Анкет Так что наследуя от basic_filebuf
не может быть и речи.
Так что я унаследовал от basic_streambuf
. Анкет Тогда я хотел связать свой mmapbuf
к FSTREAM.
Я думал, что единственное, что мне нужно было сделать, это скопировать неявный интерфейс filebuf
... но это была явная ошибка. В SGI, basic_fstream
владеет basic_filebuf
. Анкет Неважно, звоню ли я basic_filestream.std::::ios::rdbuf( streambuf* )
, FileStream полностью игнорирует его и использует свой собственный filebuf
.
Так что теперь я немного смущен ... конечно, я могу создать свой собственный mmfstream
, это была бы точная копия/вставка fstream
Но это звучит действительно не сухой.
Чего я не могу понять, так это: Почему fstream
так тесно связан с filebuf
, так что невозможно использовать ничего другого, кроме filebuf
? Весь смысл разделения потоков и BUFS заключается в том, что можно использовать поток с другим буфером.
Решения:
=> filestream
должен полагаться на неявный интерфейс filebuf
. Анкет То есть FSTREAM должен быть шаблон классом StreamBuf. Это позволило бы каждому предоставить свой собственный подкласс Streambuf для fstream
Пока он реализует filebuf
неявный интерфейс. Проблема: мы не можем добавить параметр шаблона в fstream
Поскольку это сломало бы селекторы шаблонов при использовании fstream
как шаблон шаблона.
=> filebuf
должен быть чистым виртуальным классом без каких -либо дополнительных атрибутов. Так что можно унаследовать от него, не неся весь свой файл* мусор.
Ваши идеи на эту тему?
Решение
Проверить mappen_file в Boost.iostreams библиотека. Я никогда не использовал его сам, но кажется, что это уже может сделать то, что вам нужно.
РЕДАКТИРОВАТЬ: Ой, перечитывайте ваши вопросы, и я вижу, что вы делаете это для развлечения. Возможно, вы можете черпать вдохновение из Boost.iostreams?
Другие советы
В дизайне IO Streams «Функциональность фактических потоков» (в отличие от функциональности буферов потока) реализована в std::basic_istream
, std::basic_ostream
, и их базовые классы. Классы потока строки и файлов более или менее просто удобные обертки, которые обеспечивают создание потока с правильным типом буфера.
Если вы хотите расширить потоки, Вы почти всегда хотите предоставить свой собственный класс буфера потока, И вам почти никогда не нужно предоставлять свой собственный класс потока. Анкет
После того, как у вас есть собственный тип буфера потока, вы можете сделать его буфером для любого объекта потока, который у вас есть. Или вы получаете свои собственные занятия из std::basic_istream
, std::basic_ostream
, а также std::basic_iostream
который создает экземпляр вашего буфера потока и передает его базовым классам.
Последнее удобнее для пользователей, но требует, чтобы вы написали код котла для создания экземпляра буфера (а именно конструкторы для класса потока).
Чтобы ответить на ваш вопрос: потоки файлов и файловый буфер связаны так тесно, потому что первый существует только для облегчения создания последнего. Использование потока файла позволяет легко установить все это.
Использование собственного класса потока для обертывания конструкции вашего собственного буфера потока не должно быть проблемой, так как вам в любом случае не следует передавать потоки файлов, но только (ссылки) базовым классам.
fstream
само по себе не большой класс. Это наследует от basic_stream
Чтобы обеспечить поддержку всем <<
а также >>
операции содержит специализированные steambuf
которые должны быть инициализированы, и соответствующие конструкторы для передачи параметров в streambuf
конструктор.
В некотором смысле, что вы написали о своем шаблонном решении, в порядке. Но basic_stream
также может быть получен в tcp_stream
Например. В этом случае конструкторы fstream
немного бесполезны. Таким образом, вам нужно предоставить новый tcpstream
класс, наследуя от basic_stream
с правильными параметрами для конструкторов, чтобы иметь возможность создавать tcp_stream
. Анкет В конце концов, вы ничего не будете использовать от fstream
. Анкет Создание этого нового tcpstream
это вопрос написания 3 или 4 функций.
В конце концов, вы получите из fstream
класс без какой -либо реальной причины. Это добавило бы больше связи в классовой иерархии, ненужную связь.
Весь смысл std::fstream
это то, что это _Фланг_ile на основе std::stream
. Анкет Если вы хотите обычного std::stream
при поддержке вашего mmstreambuf
, тогда вы должны создать mmstreambuf
и передать это std::stream::stream(std::streambuf*)