Может ли boost :: asio :: yield_context установить std :: error_code вместо boost :: system :: error_code?

Я пишу сетевую библиотеку C ++ 11, которая использует Boost.Asio под капотом. Я хочу показать API, который позволяет пользователям использовать сложную сопрограммы.

boost::asio::yield_context перегружает [] оператор, так что асинхронная операция может установить код ошибки, а не генерировать исключение. Например:

std::size_t n = my_socket.async_read_some(buffer, yield[ec]);
if (ec)
{
// An error occurred.
}

Моя библиотека использует std::error_code а также std::system_error сообщать об ошибках. Мой вопрос, как я могу сделать boost::asio::yield_context установить std::error_code вместо boost::system::error_code? Я бы хотел, чтобы пользователи моей библиотеки могли это делать:

std::error_code ec;
auto result = remoteProdedureCall(args, yield[ec]);
if (ec)
handleError();

где remoteProcedureCall будет выглядеть примерно так:

Result remoteProcedureCall(Args args, boost::asio::yield_context yield)
{
//...
boost::asio::async_write(socket_, argsBuffer, yield);
boost::asio::async_read(socket_, resultBuffer, yield);
if (invalidResult())
// Return a std::error_code via the yield object somehow???
// (My error codes belong to a custom error_category)
// ...
return result;
}

Постскриптум Я должен указать, что моя библиотека использует коды ошибок, которые принадлежат error_category,

0

Решение

Я закончил тем, что делал что-то намного проще, чем пытаться заставить yield_context в настройке std::error_code:

// This overload sets a std::error_code if there's an error.
Result remoteProcedureCall(Args args, boost::asio::yield_context yield,
std::error_code& userErrorCode)
{
//...
boost::system::error_code ec;
boost::async_write(socket_, buffer, yield[ec];
if (ec)
{
userErrorCode = toStdErrorCode(ec);
return Result();
}
// ...
if (someNonBoostError)
{
userErrorCode = make_error_code(myCustomErrorCode);
return Result();
}
// ...
return result;
}

// This overload throws an exception if there's an error
Result remoteProcedureCall(Args args, boost::asio::yield_context yield)
{
std::error_code ec;
auto result = remoteProcedureCall(args, yield, ec);
if (ec)
throw std::system_error(ec);
return result;
}

где toStdErrorCode преобразует из boost::system::error_code к std::error_codeсогласно Сэму ответ (также см. это связано вопрос).


Еще проще было бы сделать remoteProcedureCall взять необязательный указатель на error_code, Это позволяет избежать дублирования функций: одна устанавливает код ошибки, а другая — исключение.

2

Другие решения

Это должно работать, предполагая, ec это boost::system_error::error_code

std::make_error_code( static_cast<std::errc::errc>(ec.value()) );

Я верю boost::system::errc::errc_t перечисления отображаются на одно и то же значение в std::errc.

1