Построить std:: error_code из errno в POSIX и GetLastError() в Windows
Мой вопрос: Каков правильный способ создания экземпляров std::error_code
из errno
значений в POSIX и GetLastError()
в Windows, чтобы экземпляры можно было сравнить с известными значениями из std::errc
?
Более длинное объяснение. Моя цель - добавить экземпляр std::error_code
к самодельному объекту исключения, который работает в системах POSIX и Windows с использованием С++ 11ish.
В моем кросс-платформенном приложении я использую самодельную иерархию классов ввода-вывода, которая использует вызовы POSIX fopen()
и Windows 'CreateFile()
для открытия/создания файлов. Если это не удается, генерируется генерированное исключение типа open_error
(оно получено из std::exception
, да, но это не один из предопределенных классов исключений С++). Я пытаюсь расширить это исключение с помощью bare-bones с кодом ошибки; точнее, с С++ 11 std::error_code
, если я правильно понял.
Моя проблема заключается в том, как построить такой объект из errno
(в случае POSIX) или GetLastError()
(в случае Windows). Для POSIX, насколько я понял, я могу просто использовать конструктор errno
в std::error_code
, например. например:
std::error_code ec(errno, std::generic_category());
И что ec
должен быть сопоставим с известными значениями из std::errc
.
Для Windows, конечно же, можно сделать аналогичный вызов:
std::error_code ec(::GetLastError(), std::generic_category());
Но я не уверен, хорошо ли значения, возвращаемые GetLastError()
, хорошо знакомы с известными константами из std::errc
. Я прочитал в системной библиотеке Boost, которые они выполняют для реализации Boost error_code
, но я спрашиваю о реализации std
, а не о Boost's.
Пожалуйста, не советуйте переключаться на использование потоков С++ для доступа к файлам. Я бы с удовольствием, но рефакторинг половины моего кода - это не то, что я хотел бы сделать прямо сейчас.
Ответы
Ответ 1
Это проблема качества реализации. Константный статический объект, возвращаемый std::system_category()
, используется для выполнения сопоставления с перечислением кодов ошибок на основе платформы для стандартного перечисления std::error_condition
. В разделе 17.6.5.14 Значение кодов ошибок [value.error.codes]:
Реализации для операционных систем, не основанных на POSIX, рекомендуется определять значения, идентичные значениям операционных систем.
Вы можете видеть в http://www.boost.org/doc/libs/1_46_1/libs/system/src/error_code.cpp, как Boost выполняет сопоставление; любая стандартная библиотека, предоставленная поставщиком вашего компилятора для использования в Windows, должна делать что-то подобное.
Предполагаемое поведение описано в 19.5.1.5p4, описывающее system_category().default_error_condition(int ev)
:
Если аргумент ev
соответствует значению POSIX errno posv
, функция возвращает error_condition(posv, generic_category())
. В противном случае функция возвращает error_condition(ev, system_category())
.
Итак, например, error_code(ERROR_FILE_NOT_FOUND, std::system_category()).default_error_condition()
вызывается std::system_category().default_error_condition(ERROR_FILE_NOT_FOUND)
, который должен возвращать std::error_condition(std::no_such_file_or_directory, std::generic_category())
.