如何扩展 std::basic_streambuf 将任何可迭代序列视为流?

发布于 2024-08-20 13:04:26 字数 1337 浏览 6 评论 0原文

注意:根据回复进行编辑,以获得更合适的答案。

我有一个多年来制作的 C++ 模板集合,我称之为 Joop。它主要包含一些不太属于“通用”类别的库,但它们足够有用,以至于我不断地将它们放入不同的项目中,因此它们中的大多数在其他库(例如 Boost)中没有等效项。

这些类之一是seqstream。这个想法是,它允许您将任何可迭代序列视为普通的类似 STL 的流,其“字符​​类型”是序列的值类型。

开设此类的理由是双重的。首先,它应该提供一个接口,使任何潜在的非线性、不连续的序列看起来线性且连续;其次,它应该将流中的任何对象视为单个、复杂的大字符。有一种将流视为序列的标准方法,那么为什么不反过来呢?

目前,seqstream 包装了第一个、最后一个和当前元素的三个迭代器。我想用可以插入标准流的 basic_seqbuf 替换 seqstream 。任何人都可以提供资源让我开始扩展 std::basic_streambuf 来提供这种行为吗?

此外,如果允许可写的 seqbuf,则将对象写入 seqbuf 确实不会序列化该对象,而是使适当的调用 insert() 方法或使用用户指定的插入迭代器,例如 std::back_insert_iterator

编辑:

以下是当前如何使用seqstream的示例:

// Create a sequence of objects.
std::vector<std::string> sequence;
for (int i = 0; i < 10; ++i) {
    std::ostringstream stream;
    stream << "Element " << i << ".";
    sequence.push_back(stream.str());
}

// Create a seqstream wrapping that sequence.
joop::seqstream< std::vector<std::string> > seqstream(sequence.begin(), sequence.end());

// Read the sequence like a stream.
std::string element;
while (seqstream >> element) // OR seqstream.get(element)
    std::cout << element << '\n';

Note: Edited based on responses to receive more appropriate answers.

I have a collection of C++ templates that I've made over the years, which I call Joop. It comprises mainly libraries that don't quite fall into the "general-purpose" category but are just useful enough that I keep slapping them into different projects, so most of them don't have equivalents in other libraries such as Boost.

One of these classes is seqstream. The idea is that it allows you to treat any iterable sequence as an ordinary STL-like stream, whose "character type" is the value type of the sequence.

The rationale for this class is twofold. First, it should present an interface that makes any potentially nonlinear, noncontiguous sequence look linear and contiguous; and second, it should treat any object in the stream as though it were a single, complex, large character. There is a standard means of treating a stream as a sequence, so why not the other way around?

At present, seqstream wraps three iterators for the first, last, and current element. I want to replace seqstream with a basic_seqbuf that can be plugged into a standard stream. Can anyone provide resources to get me started on extending std::basic_streambuf to provide this kind of behaviour?

Additionally, if a writable seqbuf is allowed, it is very that writing an object to the seqbuf does not serialise the object, but makes the appropriate call to an insert() method or uses a user-specified insert iterator, such as a std::back_insert_iterator.

Edit:

Here is an example of how seqstream is currently used:

// Create a sequence of objects.
std::vector<std::string> sequence;
for (int i = 0; i < 10; ++i) {
    std::ostringstream stream;
    stream << "Element " << i << ".";
    sequence.push_back(stream.str());
}

// Create a seqstream wrapping that sequence.
joop::seqstream< std::vector<std::string> > seqstream(sequence.begin(), sequence.end());

// Read the sequence like a stream.
std::string element;
while (seqstream >> element) // OR seqstream.get(element)
    std::cout << element << '\n';

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

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

发布评论

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

评论(1

丶视觉 2024-08-27 13:04:26

查看 sstream 中的示例可能会令人困惑,但您可能根本不需要新的流类。现在查看 basic_stringstream 源代码中的示例,该类的唯一目的是提供

  • str 函数(它只是调用底层缓冲区的 str
  • 在调用其方法时避免底层缓冲区的 vtable
  • rdbuf 的返回值更改为 basic_stringbuf* (但这是不必要的,因为 str 的访问器是提供)

流类的作用非常小,除了调用 basic_streambuf 类型的底层缓冲区之外,实际上不应该具有任何功能。例如,我可以这样做:

string str( "Hello, world!" );
stringbuf buf( str ); // subclass of basic_streambuf
iostream pseudo_stringstream( &buf );
    // pseudo_stringstream can do anything a stringstream can do.
    // (not necessarily with the same syntax)

此外,所有流都应该继承自 basic_istreambasic_ostream 或两者。如果您的流未正确继承,则插入器/提取器功能可能无法工作。这些插入器声明完全没问题:

operator<<( ostream os, MyData d ); // not a template at all
       // templated, but requires correct inheritance:
template< class C > operator<<( basic_ostream<C> os, MyData d );

因此,如果您想要 iostream 行为,则需要实现 basic_streambuf 的子类并将其附加到 basic_iostream


但是,你的实际目标是什么?与通常的迭代器以及某些 back_insert_iterator 相比,内存支持的流有什么优势?您想使用与迭代相同的代码进行序列化吗?您可能希望使用 stream_iterator 让流看起来像一个序列,而不是让序列看起来像一个流。

It can be confusing to look at the examples in sstream, but you probably don't want a new stream class at all. Looking now for an example at the basic_stringstream source, the only purpose of that class is to

  • provide str function (it just calls the underlying buffer's str)
  • avoid the underlying buffer's vtable when calling its methods
  • change rdbuf's return value to basic_stringbuf* (but that's unnecessary because an accessor for str was provided)

The stream classes do very little, and really aren't supposed to have any functionality besides calling an underlying buffer of type basic_streambuf. For example, I can do this:

string str( "Hello, world!" );
stringbuf buf( str ); // subclass of basic_streambuf
iostream pseudo_stringstream( &buf );
    // pseudo_stringstream can do anything a stringstream can do.
    // (not necessarily with the same syntax)

Moreover, all streams are supposed to inherit from either basic_istream, basic_ostream, or both. Inserter/extractor functions may not work if your stream doesn't inherit correctly. These inserter declarations are perfectly fine:

operator<<( ostream os, MyData d ); // not a template at all
       // templated, but requires correct inheritance:
template< class C > operator<<( basic_ostream<C> os, MyData d );

Therefore, if you want iostream behavior, you need to implement a subclass of basic_streambuf and attach it to a basic_iostream.


But, what is your actual goal? What is the advantage of a memory-backed stream over the usual iterators and maybe some back_insert_iterators? Do you want to use the same code for serialization as for iteration? You probably want to make the stream look like a sequence using stream_iterator, not to make the sequence look like a stream.

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