我如何给stream更好的exception消息?

问题

到目前为止,对stream的exception支持是可怕的。 当Boost.System库被采用到C ++ 11中时,人们给人的印象是exception会改善。 所有的更改都是用std::system_errorreplacestd::exception 。 虽然<system_error>对开发人员来说是一个很好的库,但是标准委员会和标准库实现者并没有采取任何措施来改进exception消息。

想知道它有多糟糕,下面简要总结一下:

  • 发生错误。

  • setstate用于设置badbitfailbit

  • clearsetstate

  • 如果启用了exception, clear将会抛出一个ios_base::failure

是的,这意味着所有的错误都抛出了相同的无用的exception消息。 这是在basic_ios级别指定的,所以所有的派生类都会遇到这个问题。 违规报价:

(iostate.flags)/ 4 效果 :如果((state | (rdbuf() ? goodbit : badbit)) & exceptions()) == 0 ,则返回。 否则,该函数会抛出类basic_ios::failure (27.5.3.1.1)的对象fail ,该对象由实现定义的参数值构造。

以下是“实现定义的参数值”给我们的例子:

 ios_base::clear: unspecified iostream_category error 

有一个简单的修复?

Boost.FilesystemBoost.Iostreams都不能替代<iostream> 。 前者是一个可移植的处理文件系统的库(可能会出现在下一版C ++中),而后者与..Sources和Sinks有关。 该文档指出,它将exception委托给ios_base::failureBoost.Filesystem提供<boost/filesystem/fstream.hpp> ,它使用path而不是const char*参数来open() 。 它显示了一个如何从标准库类inheritance的例子:

  template < class charT, class traits = std::char_traits<charT> > class basic_ifstream : public std::basic_ifstream<charT,traits> { private: // disallow copying basic_ifstream(const basic_ifstream&); const basic_ifstream& operator=(const basic_ifstream&); public: basic_ifstream() {} // use two signatures, rather than one signature with default second // argument, to workaround VC++ 7.1 bug (ID VSWhidbey 38416) explicit basic_ifstream(const path& p) : std::basic_ifstream<charT,traits>(p.BOOST_FILESYSTEM_C_STR, std::ios_base::in) {} basic_ifstream(const path& p, std::ios_base::openmode mode) : std::basic_ifstream<charT,traits>(p.BOOST_FILESYSTEM_C_STR, mode) {} void open(const path& p) { std::basic_ifstream<charT,traits>::open(p.BOOST_FILESYSTEM_C_STR, std::ios_base::in); } void open(const path& p, std::ios_base::openmode mode) { std::basic_ifstream<charT,traits>::open(p.BOOST_FILESYSTEM_C_STR, mode); } virtual ~basic_ifstream() {} }; 

这是一个巧妙的把戏,除了因为我们的违规函数是非虚拟的并且一直在basic_ios ,所以我们必须重新实现一个组合爆炸:

iostream继承关系图

我怀疑整个重写是需要的,因为简单的replaceclear()是不够的。 该stream可能由于多种原因而失败,但只有一种types的exception被抛出。 虽然std::system_error为我们提供了更好的expression错误的工具,但是如果再次无法区分错误的来源,这也无济于事。

不过,我不是一个图书馆作家,不喜欢这个任务。 除了我列出的还有其他的select吗?

Boost是一个开源项目,所以我看到它有两种select:

  1. 抱怨。 要么写一个错误报告,要么进入邮件列表,并build议进行增强,或者两者兼有。 如果社区认为你有一个好点,有人可能会采取它
  2. 做1,然后做点什么。 你可能会从社区获得一些支持。 你可能不是一个图书馆作家,但也许在这个背后的人并不是,直到他们。

有没有什么神奇的方法来解决这个问题,有人要做这个工作。