How to portably compare std::system_error exceptions to std::errc values?

↘锁芯ラ 提交于 2020-01-24 08:41:52

问题


As far as I've understood, one of the best practices to check system_error conditions in a portable manner is to compare their code() value with values in the std::errc enumeration. However, when I try to run the following code, this does not seem to work.

#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!?
    }
}

Do I misunderstand how these diagnostic errors are supposed to work, or am I doing something wrong? How should one compare std::system_error exceptions to std::errc values?

EDIT: The code seems to work properly using clang++ and libc++, but fails when building against libstdc++ regardless of which GCC or Clang compiler (and version) I use. Related to PR 60555? Any portable workaround?


回答1:


You're not doing anything wrong. As confirmed in comments by T.C. and in recent similar questions, this is indeed caused by PR #60555. Fortunately, this bug was already fixed in their VCS by August 8, 2018:

Fixed on all active branches, so will be fixed in the 6.5, 7.4, 8.3 and 9.1 releases.

There seems to be no good workaround for this, so it is now just a matter of GCC developers releasing new versions of GCC and a matter of years until these get incorporated into popular distributions until we can finally start using this nice modern feature of C++11. But that's life...




回答2:


e.code() returns an instance of ::std::error_code which has overloaded operator == which leads to implicit construction of error_condition object as right hand expression out of std::errc::no_such_file_or_directory. Comparison will fail because error_code returned by exception has system_category while another one will have generic_category. You should compare with error_code::value() instead. Note that this comparison requires static_cast of std::errc value because it is an enum class and does not get implicitly converted to 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));
    }
}


来源:https://stackoverflow.com/questions/44405394/how-to-portably-compare-stdsystem-error-exceptions-to-stderrc-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!