From 8c935dc996cdf2b978ce5589606f7f658ff55ed1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 31 May 2026 14:34:01 +0300 Subject: [PATCH] Fix unwrap_and_invoke for functions returning void. Fixes #145. --- include/boost/system/unwrap_and_invoke.hpp | 25 +++++++++++++- test/Jamfile.v2 | 2 ++ test/unwrap_and_invoke3.cpp | 40 ++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 test/unwrap_and_invoke3.cpp diff --git a/include/boost/system/unwrap_and_invoke.hpp b/include/boost/system/unwrap_and_invoke.hpp index b18db3e..eb417b9 100644 --- a/include/boost/system/unwrap_and_invoke.hpp +++ b/include/boost/system/unwrap_and_invoke.hpp @@ -66,7 +66,8 @@ template int invoke_test( R& r, result const& r template(), detail::invoke_unwrap( std::declval() )... ) ), - class E = detail::get_error_type...> + class E = detail::get_error_type...>, + class En = typename std::enable_if< !std::is_void::value >::type > auto unwrap_and_invoke( F&& f, A&&... a ) -> result { @@ -82,6 +83,28 @@ auto unwrap_and_invoke( F&& f, A&&... a ) -> result return compat::invoke( std::forward(f), detail::invoke_unwrap( std::forward(a) )... ); } +template(), detail::invoke_unwrap( std::declval() )... ) ), + class E = detail::get_error_type...>, + class En1 = void, + class En2 = typename std::enable_if< std::is_void::value >::type +> +auto unwrap_and_invoke( F&& f, A&&... a ) -> result +{ + { + result r; + + using Q = int[]; + (void)Q{ detail::invoke_test( r, a )... }; + + if( !r ) return r.error(); + } + + compat::invoke( std::forward(f), detail::invoke_unwrap( std::forward(a) )... ); + + return {}; +} + // unwrap_and_construct namespace detail diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 99619af..a7e3f65 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -228,3 +228,5 @@ run unwrap_and_construct.cpp ; run unwrap_and_construct2.cpp ; run detail_is_aggregate_test.cpp ; + +run unwrap_and_invoke3.cpp ; diff --git a/test/unwrap_and_invoke3.cpp b/test/unwrap_and_invoke3.cpp new file mode 100644 index 0000000..d744036 --- /dev/null +++ b/test/unwrap_and_invoke3.cpp @@ -0,0 +1,40 @@ +// Copyright 2026 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +using namespace boost::system; + +int g_x; + +void f( int x ) +{ + g_x += x; +} + +int main() +{ + { + g_x = 0; + + result a1( 1 ); + result r = unwrap_and_invoke( f, a1 ); + + BOOST_TEST( r ); + BOOST_TEST_EQ( g_x, 1 ); + } + + { + auto ec = make_error_code( errc::invalid_argument ); + + result a1( ec ); + result r = unwrap_and_invoke( f, a1 ); + + BOOST_TEST( r.has_error() ) && BOOST_TEST_EQ( r.error(), ec ); + } + + return boost::report_errors(); +}