Должен ли я использовать system_category или generic_category для errno в Unix?

C++0x имеет два предопределенных объекта error_category: generic_category() и system_category(). Из того, что я понял до сих пор, system_category() следует использовать для ошибок, возвращаемых операционной системой, а generic_category() следует использовать для общих значений, найденных в std::errc, которые соответствуют значениям errno.

Однако что делать в Unix-подобных системах, где errno значений являются ошибками, возвращаемыми операционной системой? Должен ли я использовать system_category() (что было бы неправильно в не-Unix-подобных системах, требующих #ifdef), или я должен использовать generic_category() (что было бы неправильно в Unix-подобных системах для нестандартных значений errno)?


person CesarB    schedule 25.09.2011    source источник
comment
Прочитав ответы, я все еще не уверен, что использовать.   -  person robert    schedule 21.10.2016
comment
@robert: ‹system_error› — это запутанный, чрезмерно продуманный беспорядок. Как это правильно использовать? Никто не знает... (см. эту ветку).   -  person plexando    schedule 06.11.2020


Ответы (2)


Вы должны сообщать об ошибках из ОС (любой, включая ОС на основе POSIX, таких как Unix), используя system_category(), как это делают стандартные библиотечные функции С++ - см. цитату из стандарта С++ 11 ниже:

17.6.5.14 Значение кодов ошибок [value.error.codes]

1 Некоторые функции стандартной библиотеки C++ сообщают об ошибках через объект std::error_code (19.5.2.1). Член category() этого объекта должен возвращать std::system_category() для ошибок, происходящих из операционной системы, или ссылку на объект error_category, определенный реализацией, для ошибок, происходящих где-то еще. Реализация должна определить возможные значения value() для каждой из этих категорий ошибок. [Пример: для операционных систем, основанных на POSIX, реализациям рекомендуется определять значения std::system_category() как идентичные значениям POSIX errno, с дополнительными значениями, как определено в документации операционной системы. В реализациях для операционных систем, не основанных на POSIX, рекомендуется определять значения, идентичные значениям операционной системы. Для ошибок, которые не связаны с операционной системой, реализация может предоставлять перечисления для связанных значений. — конец примера]

person PowerGamer    schedule 03.01.2015
comment
Ну с ОС не все так однозначно, как звучит. errno исходит из библиотеки Unix (которая является частью ОС). В Windows errno происходит из среды выполнения C, которая не обязательно является частью ОС. И вы все равно не можете использовать system_category вместо errno в Windows, так как это должно быть зарезервировано для собственных ошибок Windows. Однако, если вы делаете fopen, в обоих случаях вы хотели бы обрабатывать errno одинаково. - person ysdx; 23.02.2016

Вы не должны использовать system_category, если вы на самом деле не являетесь операционной системой (или сообщаете об ошибке из функции, специфичной для ОС). Категория описывает, откуда возникла ошибка, не обязательно, что означает код ошибки. Таким образом, совершенно законно иметь набор возможных кодов ошибок из system_category таким же, как generic_category.

person Nicol Bolas    schedule 25.09.2011
comment
Давайте посмотрим, правильно ли я понимаю: я всегда должен использовать system_category(), так как значение errno я получил из функции операционной системы (или из функции, которая вызвала функцию операционной системы, или из функции, которая вызвала функцию, которая вызвала.. .). Но что делать на Win32, так как system_category() будет для GetLastError() значений, а библиотечные функции C сообщат об ошибках в errno? - person CesarB; 25.09.2011
comment
@CesarB - Это звучит как полная противоположность тому, что написал Никол Болас. :) Если errno уже было установлено вызванной вами функцией, зачем с ней возиться? Но если вам нужно возиться с этим, Никол советует вам использовать generic_category. - person Marc; 27.09.2011
comment
@Marc: я вызываю функцию, которая устанавливает errno (например, epoll_ctl или open), и я хочу выдать system_error (оборачивая errno) в случае ошибки. - person CesarB; 02.10.2011