安全重载流运算符>>

发布于 2024-08-02 11:52:11 字数 459 浏览 4 评论 0原文

有大量关于重载 operator<< 来模拟将复杂对象转换为字符串的 toString() 样式方法的信息。我还对实现相反的operator>>来将字符串反序列化为对象感兴趣。

通过检查 STL 源代码,我发现:

istream &operator>>(istream &, Object &);

将是反序列化 Object 类型的对象的正确函数签名。不幸的是,我一直不知道如何正确实现这一点 - 特别是如何处理错误:

  1. 如何指示流中的无效数据?抛出异常?
  2. 如果流中存在格式错误的数据,流应处于什么状态?
  3. 在返回操作符链接的引用之前是否应该重置任何标志?

There's a ton of information available on overloading operator<< to mimic a toString()-style method that converts a complex object to a string. I'm interested in also implementing the inverse, operator>> to deserialize a string into an object.

By inspecting the STL source, I've gathered that:

istream &operator>>(istream &, Object &);

would be the correct function signature for deserializing an object of type Object. Unfortunately, I have been at a loss for how to properly implement this - specifically how to handle errors:

  1. How to indicate invalid data in the stream? Throw an exception?
  2. What state should the stream be in if there is malformed data in the stream?
  3. Should any flags be reset before returning the reference for operator chaining?

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

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

发布评论

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

评论(3

夜空下最亮的亮点 2024-08-09 11:52:11
  1. 如何指示流中的无效数据?抛出异常?

您应该设置fail 位。如果流的用户希望抛出异常,他可以配置流(使用istream::exceptions),并且流将相应地抛出异常。我会这样做,那么

stream.setstate(ios_base::failbit);
  1. 如果流中存在格式错误的数据,流应该处于什么状态?

对于不符合您想要读取的格式的格式错误的数据,您通常应该设置 fail 位。对于内部流特定错误,使用 bad 位(例如,如果没有缓冲区连接到流)。

  1. 在返回操作符链接的引用之前是否应该重置任何标志?

我没听说过这样的事。


要检查流是否处于良好状态,可以使用 istream::sentry 类。创建它的一个对象,传递流和 true(告诉它不要立即跳过空格)。如果设置了eoffailbad位,哨兵将评估为false

istream::sentry s(stream, true);
if(!s) return stream;
// now, go on extracting data...
  1. How to indicate invalid data in the stream? Throw an exception?

You should set the fail bit. If the user of the stream wants exception to be thrown, he can configure the stream (using istream::exceptions), and the stream will throw accordingly. I would do it like this, then

stream.setstate(ios_base::failbit);
  1. What state should the stream be in if there is malformed data in the stream?

For malformed data that doesn't fit the format you want to read, you usually should set the fail bit. For internal stream specific errors, the bad bit is used (such as, if there is no buffer connected to the stream).

  1. Should any flags be reset before returning the reference for operator chaining?

I haven't heard of such a thing.


For checking whether the stream is in a good state, you can use the istream::sentry class. Create an object of it, passing the stream and true (to tell it not to skip whitespace immediately). The sentry will evaluate to false if the eof, fail or bad bit is set.

istream::sentry s(stream, true);
if(!s) return stream;
// now, go on extracting data...
时常饿 2024-08-09 11:52:11

一些附加说明:

  • 在实现运算符>>时,您可能应该考虑使用
    bufstream 而不是运算符>>的其他重载;

  • 操作过程中发生的异常应翻译为
    failbit 或 badbit(streambuf 的成员可能会抛出,具体取决于
    使用的类);

  • 设置状态可能会抛出;如果您在捕获后设置状态
    异常,您应该传播原始异常,而不是传播异常
    throwed by setstate;

  • 宽度是一个需要注意的字段。如果你是
    考虑到这一点,您应该将其重置为 0。如果您使用其他
    运算符>>要完成基本工作,您必须计算您经过的宽度
    来自您收到的;

  • 考虑考虑区域设置。

Lange 和 Kreft(标准 C++ IOStreams 和 Locales)甚至将其转换为
更多细节。他们给出了错误处理的模板代码,该代码需要
大约一页。

Some additional notes:

  • when implementing the operator>>, you probably should consider using the
    bufstream and not other overloads of operator>>;

  • exceptions occuring during the operation should be translated to the
    failbit or the badbit (members of streambuf may throw, depending on the
    class used);

  • setting the state may throw; if you set the state after catching an
    exception, you should propagate the original exception and not the one
    throwed by setstate;

  • the width is a field to which you should pay attention. If you are
    taking it into account, you should reset it to 0. If you are using other
    operator>> to do basic works, you have to compute the width you are passing
    from the one you received;

  • consider taking the locale into account.

Lange and Kreft (Standard C++ IOStreams and Locales) conver this in even
more details. They give a template code for the error handling which takes
about one page.

梦断已成空 2024-08-09 11:52:11

至于标志,我不知道某个地方是否有任何标准,但重置它们是个好主意。

Boost 有简洁的 raii 包装器:IO 状态保存器< /a>

As for flags, I don't know if there is any standard somewhere, but it is a good idea to reset them.

Boost has neat raii wrappers for that: IO State Savers

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