Boost ASIO обычно имеет дублированный API, когда одна функция может выдать исключение, а другая — нет. Например:
void close();
boost::system::error_code close(
boost::system::error_code & ec);
или
void shutdown(
shutdown_type what);
boost::system::error_code shutdown(
shutdown_type what,
boost::system::error_code & ec);
Мой вопрос: почему вторая версия функции (которая не генерирует исключение) использует возвращаемое значение (boost::system::error_code
), хотя она уже принимает переменную для указания ошибки через входной параметр (boost::system::error_code & ec
)?
Как я вижу из примеров Boost ASIO, возвращаемое значение обычно игнорируется.
Обновление 0: @Persixty отметил, что Boost ASIO имеет различия в API в разных версиях:
Другими словами, современная версия библиотеки должна возвращать void.
Пишу следует, потому что на моем хосте (Ubuntu 24.04) я использую Boost ASIO v1.83, но он все равно возвращает код ошибки:
/usr/include/boost/asio/detail/reactive_socket_service.hpp
// Disable sends or receives on the socket.
boost::system::error_code shutdown(base_implementation_type& impl,
socket_base::shutdown_type what, boost::system::error_code& ec)
{
socket_ops::shutdown(impl.socket_, what, ec);
BOOST_ASIO_ERROR_LOCATION(ec);
return ec;
}
Или:
/usr/include/boost/asio/detail/win_iocp_socket_service.hpp
// Disable sends or receives on the socket.
boost::system::error_code shutdown(base_implementation_type& impl,
socket_base::shutdown_type what, boost::system::error_code& ec)
{
socket_ops::shutdown(impl.socket_, what, ec);
return ec;
}
Чтобы помочь с контекстом, вопрос об этих перегрузках? live.boost.org/doc/libs/1_86_0/doc/html/boost_asio/reference/… и live.boost.org/doc/libs/1_86_0/doc/html/boost_asio/reference/…
@StoryTeller-UnslanderMonica ОП спрашивает, почему существует возвращаемый тип, когда уже есть второй входной параметр, а не почему существует второй параметр, когда уже есть возвращаемый тип. Кажется, вы отвечаете на последнее, но это не вопрос.
@Алан - Я ни на что не отвечаю, так как опубликовал комментарий, спекулирующий на ОП, а не ответ. Моя вторая идея, безусловно, направлена в другом направлении. Интересно, как ты мог это пропустить.
@Алан, я думаю, это две стороны одной медали. Возврат (возможно, измененный) входных данных является своего рода идиомой в функциональном программировании. даже в форме T* modify(T* arg, other_t otherarg)
, которой так много в библиотеке ISO C и различных служебных API.
@Persixty, спасибо за разъяснения! Пожалуйста, следите за обновлениями в теме.
Его нет. Он по своей сути противоречив, поскольку его нельзя использовать для непустых операций.
Разработчик Asio осознал это и отказался от возвращаемого значения. Если вы скомпилируете с BOOST_ASIO_NO_DEPRECATED
, функции вернут void
:
BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
impl_.get_service().close(impl_.get_implementation(), ec);
BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
Где config.hpp содержит:
// Helper macros to manage transition away from error_code return values.
#if defined(BOOST_ASIO_NO_DEPRECATED)
# define BOOST_ASIO_SYNC_OP_VOID void
# define BOOST_ASIO_SYNC_OP_VOID_RETURN(e) return
#else // defined(BOOST_ASIO_NO_DEPRECATED)
# define BOOST_ASIO_SYNC_OP_VOID boost::system::error_code
# define BOOST_ASIO_SYNC_OP_VOID_RETURN(e) return e
#endif // defined(BOOST_ASIO_NO_DEPRECATED)
Прекращение поддержки началось в 2017 году с первоначальным объединением изменений совместимости NetworkingTS: https://github.com/boostorg/asio/commit/b60e92b13ef68dfbb9af180d76eae41d22e19356
Удивительно, я мог только мечтать, чтобы @sehe зашел в мою тему и дал мне ответ! Раньше я думал, что вы разбираетесь в буст-парсерах, но теперь вижу, что ваш опыт гораздо шире! Спасибо!
Я вижу две возможные причины. (1) Дифференцируйте перегрузку, это необходимо, поскольку один возвращаемый тип не поможет. (2) Бедняк
nodsicard
. Это заставляет сохранять код возврата, сохраняя при этомif ( ... == boost::system::some_code ) { do_stuff(); }
, что выглядит идиоматично.