如何扩展 std::basic_streambuf 将任何可迭代序列视为流?
注意:根据回复进行编辑,以获得更合适的答案。
我有一个多年来制作的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
查看 sstream 中的示例可能会令人困惑,但您可能根本不需要新的流类。现在查看
basic_stringstream
源代码中的示例,该类的唯一目的是提供str
函数(它只是调用底层缓冲区的str
)rdbuf
的返回值更改为basic_stringbuf*
(但这是不必要的,因为str
的访问器是提供)流类的作用非常小,除了调用
basic_streambuf
类型的底层缓冲区之外,实际上不应该具有任何功能。例如,我可以这样做:此外,所有流都应该继承自
basic_istream
、basic_ostream
或两者。如果您的流未正确继承,则插入器/提取器功能可能无法工作。这些插入器声明完全没问题:因此,如果您想要 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 thebasic_stringstream
source, the only purpose of that class is tostr
function (it just calls the underlying buffer'sstr
)rdbuf
's return value tobasic_stringbuf*
(but that's unnecessary because an accessor forstr
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: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:Therefore, if you want iostream behavior, you need to implement a subclass of
basic_streambuf
and attach it to abasic_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_iterator
s? Do you want to use the same code for serialization as for iteration? You probably want to make the stream look like a sequence usingstream_iterator
, not to make the sequence look like a stream.