Подтвердить что ты не робот

Построить 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.

Пожалуйста, не советуйте переключаться на использование потоков С++ для доступа к файлам. Я бы с удовольствием, но рефакторинг половины моего кода - это не то, что я хотел бы сделать прямо сейчас.

4b9b3361

Ответ 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()).