Как преобразовать errno в исключение, используя <system_error>

Я прочитал вдумчивую серию постов в блоге о новом <system_error> заголовок в C++11. Он говорит, что заголовок определяет error_code класс, представляющий конкретное значение ошибки, возвращаемое операцией (такой как системный вызов). Он говорит, что заголовок определяет system_error класс, который является классом исключения (наследуется от runtime_exception) и используется для упаковки error_codess.

То, что я хочу знать, это как на самом деле конвертировать системную ошибку из errno в system_error так что я могу бросить это. Например, POSIX open функция сообщает об ошибках, возвращая -1 и устанавливая errnoИтак, если я хочу вызвать исключение, как я должен завершить код ниже?

void x()
{
    fd = open("foo", O_RDWR);
    if (fd == -1)
    {
        throw /* need some code here to make a std::system_error from errno */;
    }
}

Я случайно попробовал:

errno = ENOENT;
throw std::system_error();

но полученное исключение не возвращает информацию, когда what() называется.

Я знаю, что мог сделать throw errno; но я хочу сделать это правильно, используя новый <system_error> заголовок.

Есть конструктор для system_error это занимает один error_code в качестве аргумента, так что если я могу просто преобразовать errno в error_code тогда все остальное должно быть очевидным.

Это кажется очень простой вещью, поэтому я не знаю, почему я не могу найти хороший учебник по этому вопросу.

Я использую gcc 4.4.5 на процессоре ARM, если это имеет значение.

2 ответа

Решение

Вы на правильном пути, просто передайте код ошибки и std::generic_category возражать против std::system_error конструктор и он должен работать.

Пример:

#include <assert.h>
#include <errno.h>
#include <iostream>
#include <system_error>

int main()
{
    try
    {
        throw std::system_error(EFAULT, std::generic_category());
    }
    catch (std::system_error& error)
    {
        std::cout << "Error: " << error.code() << " - " << error.what() << '\n';
        assert(error.code() == std::errc::bad_address);
    }
}

Выход из вышеуказанной программы на моей системе

Ошибка: общий:14 - неверный адрес

Чтобы добавить к отличному принятому ответу, вы можете дополнить сообщение об ошибке некоторой контекстной информацией в третьем аргументе, например, неудачным именем файла:

      std::string file_name = "bad_file_name.txt";
fd = open(file_name, O_RDWR);
if (fd < 0) {
    throw std::system_error(errno, std::generic_category(), file_name);
}

Затем, когда поймали, e.what() вернется, например:

      bad_file_name.txt: file not found
Другие вопросы по тегам