Почему первый параметр конструктора std :: error_code зафиксирован на int

С тех пор, как я узнал о std :: error_code, я часто его использую, и мне нравится минималистичный и гибкий дизайн этой библиотеки. Но меня беспокоит одна проблема. В чем причина определять конструктор std :: error_code следующим образом:

error_code( int ec, const error_category& ecat ) noexcept;

Это предотвращает использование клиентами 64-битных кодов ошибок в среде, где int компилируется с 32-битными (что верно для всех компиляторов Visual Studio). Разве не было бы более гибким использование типа, который можно адаптировать к платформе, например std::size_t? Или, чтобы предоставить пользователю полный контроль над базовым целочисленным типом, ввести класс шаблона std::basic_error_code, чтобы получить поведение, подобное std::basic_string с его определениями типов std::string и std::wstring:

namespace std
{
    template<class IntT>
    class basic_error_code
    {  
    public:
        basic_error_code(IntT ec, const error_category& cat)
            : _Myec(ec)
            , _Mycat(&cat)
        {}

        ...

    private:
        IntT  _Myec;
        const error_category *_Mycat;
    };

    using error_code = basic_error_code<int>;
} // namespace std

Конечно, необходимо добавить дополнительный конструктор преобразования для 64-битных error_codes, чтобы иметь возможность работать с std::error_code, который использует 32-битные версии, но в настоящее время я не вижу проблем с его определением.

Обновлять

Я ценю все ваши ответы и, конечно же, в целом вы правы; нет необходимости в таком количестве кодов ошибок.

Но позвольте мне привести два примера, где, тем не менее, это имело бы смысл:

  1. Если у вас есть существующий код из другой системы, которая не использует std :: error_code, и этот код использует 64-битные значения (возможно, вы не хотите использовать все эти коды, а только sup-диапазон). Вы можете легко преобразовать этот код в std :: error_code, определив свою собственную категорию. Если у вас есть дополнительный список #define всех этих кодов, на самом деле это всего лишь небольшая копия и вставка, потому что вы можете использовать имена макросов #define прямо в своем перечислении.

  2. Если вы хотите использовать | операция по объединению разных error_codes в один. Это возможно и очень хорошо работает в сочетании с фреймворком std :: error_code (я уже реализовал такую ​​систему). В этом случае вы очень быстро теряете возможности, если можете использовать только 32-битную версию. Что ж, прежде чем вы будете жаловаться на уникальность error_code, который представляет собой комбинацию разных error_codes; на самом деле это не проблема, потому что у вас есть условия ошибки, которые могут замаскировать нежелательную часть error_code, чтобы получить исходный error_code (тот, который был у вас до использования операции |)

Я с нетерпением жду дальнейших комментариев по этой теме.

вам действительно нужно более 2 ^ 32 кодов ошибок?

463035818_is_not_a_number 10.08.2018 16:14

Если ваш код может выйти из строя более чем 4 миллиардами способов и вам нужно более 2 ^ 32 кодов ошибок, вы можете просто создать вторую категорию, которая будет охватывать вторые 4 миллиарда различных способов, которыми ваш код может выйти из строя ...

Alan Birtles 10.08.2018 16:15

Боюсь, на ваш вопрос нет лучшего ответа, чем: потому что этого достаточно

463035818_is_not_a_number 10.08.2018 16:17

Наличие basic_error_code не имеет смысла - весь смысл std::error_code заключается в унификации отчетов об ошибках, а не в их дальнейшем разделении.

StaceyGirl 10.08.2018 16:29

У вас есть реальная система, для которой 32-битной версии недостаточно (мне любопытно, все известные мне системы используют не более 32-битных кодов)?

geza 10.08.2018 17:19

std :: error_code не обязательно должен содержать только коды, которые представляют условия ошибки. Также хорошо определенные состояния программы могут быть переданы с помощью std :: error_code. Например, представьте себе категорию ошибки, которая сопоставляет error_code с ответом REST. У вас обязательно будет error_code «200», что означает: «все в порядке».

Flow Rei Ser 10.08.2018 19:37
0
6
128
1

Ответы 1

std::error_code предназначен для обертывания / замены различных существующих систем ошибок, таких как errno и HRESULT, которые используют 32-битные коды ошибок (int в случае errno и LONG для HRESULT).

Я не могу представить себе ситуацию, когда вам понадобится более 4 миллиардов (2 ^ 32) кодов ошибок в одной категории. Например, errno предоставляет коды ошибок для большинства posix с примерно 130 кодами ошибок.

Использование более крупного типа без всякой пользы потребует большего использования памяти.

Есть заметное исключение из того, что «больший тип потребует больше памяти без всякой пользы»: 64-битные системы. error_category хранится как указатель на error_code, поэтому из-за заполнения 64-битный ec не увеличивает размер.

geza 10.08.2018 17:22

Другие вопросы по теме