I'm writing a C++11 networking library that uses Boost.Asio under the hood. I want to expose an API that allows users to use stackful coroutines.
boost::asio::yield_context
overloads the []
operator so that an asynchronous operation may set an error code instead of throwing an exception. For example:
std::size_t n = my_socket.async_read_some(buffer, yield[ec]);
if (ec)
{
// An error occurred.
}
My library uses std::error_code
and std::system_error
to report errors. My question is how can I make boost::asio::yield_context
set a std::error_code
instead of boost::system::error_code
? I'd like users of my library to be able to do this:
std::error_code ec;
auto result = remoteProdedureCall(args, yield[ec]);
if (ec)
handleError();
where remoteProcedureCall
would look something like:
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;
}
PS I should indicate that my library uses error codes that belong to a custom error_category
.
I ended-up doing something much simpler than trying to coerce yield_context
into setting an 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;
}
where toStdErrorCode
converts from a boost::system::error_code
to a std::error_code
, as per Sam's answer (also see this related question ).
Even simpler would be to make remoteProcedureCall
take an optional pointer to an error_code
. This avoids having duplicate functions: one that sets the error code, and another that throws an exception.
This should work, assuming ec
is a boost::system_error::error_code
std::make_error_code( static_cast<std::errc::errc>(ec.value()) );
I believe the boost::system::errc::errc_t
enums are mapped to the same value in std::errc
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.