从streambuf派生而不重写相应的流

发布于 2024-09-05 07:41:46 字数 1145 浏览 13 评论 0原文

几天前,我决定编写一个使用 mmap 和预读的 streambuf 子类会很有趣。 我查看了我的 STL (SGI) 如何实现 filebuf 并意识到 basic_filebuf 包含一个 FILE*。因此从 basic_filebuf 继承是不可能的。

所以我继承自basic_streambuf。然后我想将我的 mmapbuf 绑定到 fstream。

我认为我唯一要做的就是复制 filebuf 的隐式接口...但这显然是一个错误。在SGI中,basic_fstream拥有一个basic_filebuf。无论我是否调用 basic_filestream.std::::ios::rdbuf(streambuf* ),文件流都会完全忽略它并使用自己的 filebuf。

所以现在我有点困惑......当然,我可以创建自己的 mmfstream,这将是 fstream 的精确复制/粘贴,但这听起来确实不是以干为主。

我无法理解的是:为什么fstreamfilebuf如此紧密地结合在一起,以至于除了之外不可能使用其他任何东西>filebuf 分离流和 buf 的要点在于,可以使用具有不同缓冲区的流。

解决方案:

=> filestream应该依赖于filebuf的隐式接口。也就是说,fstream 应该由streambuf 类模板化。这将允许每个人都向 fstream 提供自己的 Streambuf 子类,只要它实现 filebuf 的隐式接口即可。问题:我们无法向 fstream 添加模板参数,因为在使用 fstream 作为模板模板参数时,它会破坏模板选择器。

=> filebuf 应该是一个纯虚拟类,没有任何附加属性。这样就可以继承它而无需携带其所有 FILE* 垃圾。

您对这个问题的想法?

Some days ago, I decided that it would be fun to write a streambuf subclass that would use mmap and read-ahead.
I looked at how my STL (SGI) implemented filebuf and realized that basic_filebuf contains a FILE*. So inheriting from basic_filebuf is out of the question.

So I inherited from basic_streambuf. Then i wanted to bind my mmapbuf to a fstream.

I thought the only thing that I would have to do would be to copy the implicit interface of filebuf... but that was a clear mistake. In the SGI, basic_fstream owns a basic_filebuf. No matter if I call basic_filestream.std::::ios::rdbuf( streambuf* ), the filestream completely ignores it and uses its own filebuf.

So now I'm a bit confused... sure, I can create my own mmfstream, that would be the exact copy/paste of the fstream but that sounds really not DRY-oriented.

What I can't understand, is: why does fstream is so tightly coupled with filebuf, so that it is not possible to use anything else than a filebuf? The whole point of separating streams and bufs is that one can use a stream with a different buffer.

Solutions:

=> filestream should rely on the implicit interface of filebuf. That is, fstream should be templated by a streambuf class. That would allow everyone to provide its own streambuf subclass to a fstream as long as it implements filebuf's implicit interface. Problem: we cannot add a template parameter to fstream since it would break template selectors while using fstream as template template parameter.

=> filebuf should be a pure virtual class without any additional attributes. So that one can inherit from it without carrying all its FILE* garbage.

Your ideas on the subject ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

会傲 2024-09-12 07:41:46

在 IO 流的设计中,大多数实际流的功能(与流缓冲区的功能相反)是在 std::basic_istreamstd::basic_ostream 中实现的,以及他们的基类。 字符串和文件流类或多或少只是方便的包装器,可确保实例化具有正确类型缓冲区的流

如果您想扩展流,您几乎总是希望提供自己的流缓冲区类,并且您几乎不需要提供自己的流类。 。

一旦您拥有自己的流缓冲区类型,您就可以将其作为您碰巧拥有的任何流对象的缓冲区。或者,您可以从 std::basic_istreamstd::basic_ostreamstd::basic_iostream 派生自己的类,它们实例化您的流缓冲区并传递它到他们的基类。
后者对用户来说更方便,但需要您为缓冲区的实例化编写一些样板代码(即流类的构造函数)。

回答你的问题:文件流和文件缓冲区耦合如此紧密,因为前者的存在只是为了简化后者的创建。使用文件流可以轻松完成所有设置。
使用您自己的流类来包装您自己的流缓冲区的构造应该不是问题,因为您无论如何都不应该传递文件流,而只能(引用)基类。

In the IO streams' design, most of the actual streams' functionality (as opposed to the stream buffers' functionality) is implemented in std::basic_istream, std::basic_ostream, and their base classes. The string and file stream classes are more or less just convenience wrappers which make sure a stream with the right type of buffer is instantiated.

If you want to extend the streams, you almost always want to provide your own stream buffer class, and you almost never need to provide your own stream class. .

Once you have your own stream buffer type, you can then make it the buffer for any stream object you happen to have around. Or you derive your own classes from std::basic_istream, std::basic_ostream, and std::basic_iostream which instantiates your stream buffer and pass it to their base classes.
The latter is more convenient for users, but requires you to write some boiler-plate code for the buffer's instantiation (namely constructors for the stream class).

To answer your question: File streams and file buffer are coupled so tightly because the former only exists to ease the creation of the latter. Using a file stream makes it easy to set it all up.
Using your own stream class to wrap construction of your own stream buffer shouldn't be a problem, since you shouldn't be passing around file streams anyway, but only (references) to the base classes.

祁梦 2024-09-12 07:41:46

查看 mapped_file Boost.Iostreams 库。我自己从未使用过它,但看起来它可能已经满足了您的需要。

编辑:哎呀,重读你的问题,我发现你这样做是为了好玩。或许你可以从Boost.Iostreams中汲取灵感?

Check out mapped_file in the Boost.Iostreams library. I've never used used it myself, but it seems like it might already do what you need.

EDIT: Oops, reread your questions and I see you're doing this for fun. Perhaps you can draw inspiration from Boost.Iostreams?

栀子花开つ 2024-09-12 07:41:46

fstream 本身并不是一个大类。它继承自basic_stream,为所有<<>>操作提供支持,包含一个专门的steambuf< /code> 必须初始化,以及相应的构造函数将参数传递给 streambuf 构造函数。

从某种意义上说,您所写的有关模板化解决方案的内容是可以的。但是,basic_stream 也可以派生为 tcp_stream。在这种情况下,fstream 的构造函数就有点无用了。因此,您需要提供一个新的 tcpstream 类,该类继承自 basic_stream,并为构造函数提供正确的参数,以便能够创建 tcp_stream。最后,您不会使用 fstream 中的任何内容。创建这个新的 tcpstream 只需编写 3 或 4 个函数即可。

最后,您将在没有任何真正理由的情况下从 fstream 类派生。这会在类层次结构中增加更多的耦合,即不必要的耦合。

fstream in itself is not a big class. It inherits from basic_stream to provide support for all the << and >> operations, contains a specialized steambuf that have to be initialized, and the corresponding constructors to pass the parameters to the streambuf constructor.

In a sense, what you wrote about your templated solution is OK. But basic_stream can also be derived into a tcp_stream for example. In that case, the constructors of fstream are a bit useless. Thus you need to provide a new tcpstream class, inheriting from basic_stream with the correct parameters for the constructors to be able to create the tcp_stream. In the end, you wouldn't use anything from fstream. Creating this new tcpstream is a matter of writing 3 or 4 functions only.

In the end, you would derive from the fstream class without any real reason to. This would add more coupling in the class hierarchy, unneeded coupling.

唱一曲作罢 2024-09-12 07:41:46

std::fstream 的全部要点在于它是基于 _F_ile 的 std::stream。如果您想要一个由 mmstreambuf 支持的普通 std::stream,那么您应该创建一个 mmstreambuf 并将其传递给 std: :stream::stream(std::streambuf*)

The whole point of std::fstream is that it is a _F_ile based std::stream. If you want an ordinary std::stream backed by your mmstreambuf, then you should create a mmstreambuf and pass it to std::stream::stream(std::streambuf*)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文