如何将std :: system_error异常与std :: errc值进行可移植的比较?

时间:2017-06-07 06:45:54

标签: c++ c++11 error-handling c++-standard-library compiler-bug

据我所知,以便携式方式检查system_error条件的最佳做法之一是将code()值与std::errc枚举中的值进行比较。但是,当我尝试运行以下代码时,这似乎不起作用。

#include <cassert>
#include <cerrno>
#include <system_error>

int main() {
    try {
        throw std::system_error(ENOENT, std::system_category());
    } catch (std::system_error const & e) {
        assert(e.code() == std::errc::no_such_file_or_directory); // <- FAILS!?
    }
}

我是否误解了这些诊断错误应该如何工作,或者我做错了什么?如何将std::system_error例外与std::errc值进行比较?

编辑:代码似乎使用clang++和libc ++正常工作,但在构建libstdc ++时失败,无论我使用哪个GCC或Clang编译器(和版本)。与PR 60555相关?任何便携式解决方法?

2 个答案:

答案 0 :(得分:0)

您没有做错任何事情。正如T.C.的评论所证实在recent similar questions中,这确实是由PR #60555引起的。幸运的是,该错误已在2018年8月8日之前在其VCS中修复:

  

已修复所有活动分支,因此将在6.5、7.4、8.3和9.1版本中进行修复。

似乎没有很好的解决方法,因此,这只是GCC开发人员发布新版本的GCC的问题,而且要花几年的时间才能将它们合并到流行的发行版中,直到我们最终可以开始使用此出色的现代功能为止C ++ 11。但这就是生活...

答案 1 :(得分:-1)

e.code()会返回::std::error_code的实例,该实例已超载operator ==,导致隐式构造error_condition对象作为std::errc::no_such_file_or_directory中的右手表达式。比较将失败,因为异常返回的error_code具有system_category,而另一个将具有generic_category。您应该与error_code::value()进行比较。请注意,此比较需要static_cast std::errc值,因为它是enum class并且不会隐式转换为int。 Working example

#include <cassert>
#include <cerrno>
#include <system_error>
#include <iostream>
 
int main()
{
    ::std::cout << static_cast< int >(ENOENT) << ::std::endl;
    ::std::cout << static_cast< int >(::std::errc::no_such_file_or_directory) << ::std::endl;
    try
    {
        throw std::system_error(ENOENT, std::system_category());
    }
    catch(::std::system_error const & e)
    {
        assert(e.code().value() == static_cast< int >(::std::errc::no_such_file_or_directory));
    }
}