如何创建自己的ostream / streambuf?

时间:2022-10-19 07:21:11

For educational purposes I want to create a ostream and stream buffer to do:

出于教育目的,我想创建一个ostream和流缓冲区来做:

  1. fix endians when doing << myVar;
  2. 做<< myVar时修复endians;

  3. store in a deque container instead of using std:cout or writing to a file
  4. 存储在deque容器中而不是使用std:cout或写入文件

  5. log extra data, such as how many times I did <<, how many times I did .write, the amount of bytes I written and how many times I flush(). But I do not need all the info.
  6. 记录额外的数据,例如我做了多少次<<,我做了多少次.write,我写的字节数和flush()的次数。但我不需要所有的信息。

I tried overloading but failed horribly. I tried overloading write by doing

我试过重载但是失败了。我试着通过写过载

ostream& write( const char* s, streamsize n ) 

in my basic_stringstream2 class (I copied paste basic_stringstream into my cpp file and modified it) but the code kept using basic_ostream. I looked through code and it looks like I need to overload xsputn (which isn't mention on this page http://www.cplusplus.com/reference/iostream/ostream ) but what else do I need to overload? and how do I construct my class (what does it need to inherit, etc)?

在我的basic_stringstream2类中(我将paste basic_stringstream粘贴到我的cpp文件中并对其进行修改)但代码保持使用basic_ostream。我查看了代码,看起来我需要重载xsputn(这个页面上没有提到http://www.cplusplus.com/reference/iostream/ostream)但是我还需要重载多少?以及如何构建我的类(它需要继承什么等)?

3 个解决方案

#1


24  

The canonical approach consists in defining your own streambuf. You should have a look at:

规范方法包括定义自己的streambuf。你应该看看:

#2


6  

For A+C) I think you should look at facets, they modify how objects are written as characters. You could store statistics here as well on how many times you streamed your objects. Check out How to format my own objects when using STL streams? for an example.

对于A + C)我认为你应该看一下facets,它们会修改对象作为字符的写法。您可以在此处存储统计信息以及流式传输对象的次数。查看如何在使用STL流时格式化我自己的对象?举个例子。

For B) You need to create your own streambuf and connect your ostream to that buffer (constructor argument). See Luc's links + Deriving new streambuf classes. In short you need to implement this for an ostream (minimum):

对于B)您需要创建自己的streambuf并将您的ostream连接到该缓冲区(构造函数参数)。查看Luc的链接+推导新的streambuf课程。总之,你需要为ostream(最小)实现这个:

  • overflow (put a single char or flush buffer) (link)
  • 溢出(放一个字符或刷新缓冲区)(链接)

  • xsputn (put a char array to buffer)(link)
  • xsputn(将一个char数组放到缓冲区)(链接)

  • sync (link)

#3


1  

I'm not sure that what you want to do is possible. The << operators are not virtual. So you could define yourstream &operator << (yourstream &strm, int i) to do what you want with the endian conversion and counting, and it will work when your code calls it directly. But if you pass a yourstream object into a function that expects an ostream, any time that function calls <<, it will go to the original ostream version instead of yours.

我不确定你想做什么是可能的。 < <运营商不是虚拟的。因此,您可以定义yourstream&operator <<(yourstream&strm,int i)以使用endian转换和计数执行您想要的操作,并且当您的代码直接调用它时它将起作用。但是如果你将一个yourstream对象传递给一个需要ostream的函数,那么只要该函数调用<<,它就会转到原来的ostream版本而不是你的版本。< p>

As I understand it, the streams facilities have been set up so that you can "easily" define a new stream type which uses a different sort of buffer (like, say, a deque of chars), and you can very easily add support for outputting your own classes via <<. I don't think you are intended to be able to redefine the middle layer between those.

根据我的理解,已经设置了流设施,以便您可以“轻松”定义使用不同类型缓冲区的新流类型(例如,字符的deque),并且您可以非常轻松地添加对通过< <输出自己的类。我不认为你打算能够重新定义它们之间的中间层。< p>

And particularly, the entire point of the << interface is to provide nicely formatted text output, while it sounds like you actually want binary output. (Otherwise the reference to "endian" makes no sense.) Even assuming there is some way of doing this I don't know, it will produce awkward binary output at best. For instance, consider the end user overload to output a point in 3D space. The end user version of << will probably do something like << '(' << x << ", " << y << ", " << z << ')'. That will look nice in a text stream, but it's a lot of wasted and completely useless characters in a binary stream, which would ideally just use << x << y << z. (And how many calls to << should those count as?)

特别是,< <界面的整个要点是提供格式良好的文本输出,而听起来你实际上想要二进制输出。 (否则对“endian”的引用毫无意义。)即使假设有一些方法可以做到这一点我也不知道,它最多会产生笨拙的二进制输出。例如,考虑最终用户过载以在3d空间中输出点。 <<的最终用户版本可能会执行类似<<'('<< x <<“,”<< y z <<')'的操作。这在文本流中看起来很不错,但是在二进制流中有很多浪费且完全无用的字符,理想情况下只使用<< << z。 (还有多少次调用<<应该算什么呢?)< p>

#1


24  

The canonical approach consists in defining your own streambuf. You should have a look at:

规范方法包括定义自己的streambuf。你应该看看:

#2


6  

For A+C) I think you should look at facets, they modify how objects are written as characters. You could store statistics here as well on how many times you streamed your objects. Check out How to format my own objects when using STL streams? for an example.

对于A + C)我认为你应该看一下facets,它们会修改对象作为字符的写法。您可以在此处存储统计信息以及流式传输对象的次数。查看如何在使用STL流时格式化我自己的对象?举个例子。

For B) You need to create your own streambuf and connect your ostream to that buffer (constructor argument). See Luc's links + Deriving new streambuf classes. In short you need to implement this for an ostream (minimum):

对于B)您需要创建自己的streambuf并将您的ostream连接到该缓冲区(构造函数参数)。查看Luc的链接+推导新的streambuf课程。总之,你需要为ostream(最小)实现这个:

  • overflow (put a single char or flush buffer) (link)
  • 溢出(放一个字符或刷新缓冲区)(链接)

  • xsputn (put a char array to buffer)(link)
  • xsputn(将一个char数组放到缓冲区)(链接)

  • sync (link)

#3


1  

I'm not sure that what you want to do is possible. The << operators are not virtual. So you could define yourstream &operator << (yourstream &strm, int i) to do what you want with the endian conversion and counting, and it will work when your code calls it directly. But if you pass a yourstream object into a function that expects an ostream, any time that function calls <<, it will go to the original ostream version instead of yours.

我不确定你想做什么是可能的。 < <运营商不是虚拟的。因此,您可以定义yourstream&operator <<(yourstream&strm,int i)以使用endian转换和计数执行您想要的操作,并且当您的代码直接调用它时它将起作用。但是如果你将一个yourstream对象传递给一个需要ostream的函数,那么只要该函数调用<<,它就会转到原来的ostream版本而不是你的版本。< p>

As I understand it, the streams facilities have been set up so that you can "easily" define a new stream type which uses a different sort of buffer (like, say, a deque of chars), and you can very easily add support for outputting your own classes via <<. I don't think you are intended to be able to redefine the middle layer between those.

根据我的理解,已经设置了流设施,以便您可以“轻松”定义使用不同类型缓冲区的新流类型(例如,字符的deque),并且您可以非常轻松地添加对通过< <输出自己的类。我不认为你打算能够重新定义它们之间的中间层。< p>

And particularly, the entire point of the << interface is to provide nicely formatted text output, while it sounds like you actually want binary output. (Otherwise the reference to "endian" makes no sense.) Even assuming there is some way of doing this I don't know, it will produce awkward binary output at best. For instance, consider the end user overload to output a point in 3D space. The end user version of << will probably do something like << '(' << x << ", " << y << ", " << z << ')'. That will look nice in a text stream, but it's a lot of wasted and completely useless characters in a binary stream, which would ideally just use << x << y << z. (And how many calls to << should those count as?)

特别是,< <界面的整个要点是提供格式良好的文本输出,而听起来你实际上想要二进制输出。 (否则对“endian”的引用毫无意义。)即使假设有一些方法可以做到这一点我也不知道,它最多会产生笨拙的二进制输出。例如,考虑最终用户过载以在3d空间中输出点。 <<的最终用户版本可能会执行类似<<'('<< x <<“,”<< y z <<')'的操作。这在文本流中看起来很不错,但是在二进制流中有很多浪费且完全无用的字符,理想情况下只使用<< << z。 (还有多少次调用<<应该算什么呢?)< p>