diff --git a/appveyor.yml b/appveyor.yml index f9feb5a..6018f24 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,7 +17,11 @@ environment: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 TOOLSET: msvc-14.1 CXXSTD: 14,17,latest - ADDRMD: 32,64 + ADDRMD: 32 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + TOOLSET: msvc-14.1 + CXXSTD: 14,17,latest + ADDRMD: 64 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 ADDPATH: C:\cygwin64\bin; TOOLSET: gcc diff --git a/include/boost/system/result.hpp b/include/boost/system/result.hpp index 03ab010..456a792 100644 --- a/include/boost/system/result.hpp +++ b/include/boost/system/result.hpp @@ -73,10 +73,10 @@ BOOST_NORETURN BOOST_NOINLINE inline void throw_exception_from_error( std::excep // in_place_* using in_place_value_t = variant2::in_place_index_t<0>; -constexpr in_place_value_t in_place_value{}; +BOOST_INLINE_CONSTEXPR in_place_value_t in_place_value{}; using in_place_error_t = variant2::in_place_index_t<1>; -constexpr in_place_error_t in_place_error{}; +BOOST_INLINE_CONSTEXPR in_place_error_t in_place_error{}; namespace detail { @@ -1124,7 +1124,8 @@ result& operator|=( result& r, F&& f ) template()( std::declval() ) ), - class En = typename std::enable_if::value>::type + class En1 = typename std::enable_if::value>::type, + class En2 = typename std::enable_if::value>::type > result operator&( result const& r, F&& f ) { @@ -1140,7 +1141,8 @@ result operator&( result const& r, F&& f ) template()( std::declval() ) ), - class En = typename std::enable_if::value>::type + class En1 = typename std::enable_if::value>::type, + class En2 = typename std::enable_if::value>::type > result operator&( result&& r, F&& f ) { @@ -1154,9 +1156,44 @@ result operator&( result&& r, F&& f ) } } +template()( std::declval() ) ), + class En = typename std::enable_if::value>::type +> +result operator&( result const& r, F&& f ) +{ + if( r.has_error() ) + { + return r.error(); + } + else + { + std::forward( f )( *r ); + return {}; + } +} + +template()( std::declval() ) ), + class En = typename std::enable_if::value>::type +> +result operator&( result&& r, F&& f ) +{ + if( r.has_error() ) + { + return r.error(); + } + else + { + std::forward( f )( *std::move( r ) ); + return {}; + } +} + template()() ), - class En = typename std::enable_if::value>::type + class En1 = typename std::enable_if::value>::type, + class En2 = typename std::enable_if::value>::type > result operator&( result const& r, F&& f ) { @@ -1170,6 +1207,23 @@ result operator&( result const& r, F&& f ) } } +template()() ), + class En = typename std::enable_if::value>::type +> +result operator&( result const& r, F&& f ) +{ + if( r.has_error() ) + { + return r.error(); + } + else + { + std::forward( f )(); + return {}; + } +} + // result & unary-returning-result template& operator&=( result& r, F&& f ) return r; } +template()() ), + class En = typename std::enable_if::value>::type +> +result& operator&=( result& r, F&& f ) +{ + if( r ) + { + std::forward( f )(); + } + + return r; +} + // result &= unary-returning-result template r; + fv_called = 0; + + r &= fv; + + BOOST_TEST( r.has_value() ); + BOOST_TEST_EQ( fv_called, 1 ); + } + + { + result r( in_place_error ); + fv_called = 0; + + r &= fv; + + BOOST_TEST( r.has_error() ); + BOOST_TEST_EQ( fv_called, 0 ); + } + return boost::report_errors(); } diff --git a/test/result_and_fn1v.cpp b/test/result_and_fn1v.cpp index 929bef5..2f5d51f 100644 --- a/test/result_and_fn1v.cpp +++ b/test/result_and_fn1v.cpp @@ -55,6 +55,20 @@ int k() return 7; } +static int fv1_called_with; + +void fv1( int x ) +{ + fv1_called_with = x; +} + +static int fv2_called; + +void fv2() +{ + ++fv2_called; +} + int main() { { @@ -199,5 +213,119 @@ int main() BOOST_TEST( r2.has_error() ); } + { + fv1_called_with = 0; + + result r( 1 ); + result r2 = r & fv1; + + BOOST_TEST( r2.has_value() ); + BOOST_TEST_EQ( fv1_called_with, 1 ); + } + + { + result const r( 1 ); + result r2 = r & fv1; + + BOOST_TEST( r2.has_value() ); + BOOST_TEST_EQ( fv1_called_with, 1 ); + } + + { + fv1_called_with = 0; + + result r2 = result( 1 ) & fv1; + + BOOST_TEST( r2.has_value() ); + BOOST_TEST_EQ( fv1_called_with, 1 ); + } + + { + fv1_called_with = 0; + + result r( in_place_error ); + result r2 = r & fv1; + + BOOST_TEST( r2.has_error() ); + BOOST_TEST_EQ( fv1_called_with, 0 ); + } + + { + fv1_called_with = 0; + + result const r( in_place_error ); + result r2 = r & fv1; + + BOOST_TEST( r2.has_error() ); + BOOST_TEST_EQ( fv1_called_with, 0 ); + } + + { + fv1_called_with = 0; + + result r2 = result( in_place_error ) & fv1; + + BOOST_TEST( r2.has_error() ); + BOOST_TEST_EQ( fv1_called_with, 0 ); + } + + { + result r; + fv2_called = 0; + + result r2 = r & fv2; + + BOOST_TEST( r2.has_value() ); + BOOST_TEST_EQ( fv2_called, 1 ); + } + + { + result const r; + fv2_called = 0; + + result r2 = r & fv2; + + BOOST_TEST( r2.has_value() ); + BOOST_TEST_EQ( fv2_called, 1 ); + } + + { + fv2_called = 0; + + result r2 = result() & fv2; + + BOOST_TEST( r2.has_value() ); + BOOST_TEST_EQ( fv2_called, 1 ); + } + + { + result r( in_place_error ); + fv2_called = 0; + + result r2 = r & fv2; + + BOOST_TEST( r2.has_error() ); + BOOST_TEST_EQ( fv2_called, 0 ); + } + + { + result const r( in_place_error ); + fv2_called = 0; + + result r2 = r & fv2; + + BOOST_TEST( r2.has_error() ); + BOOST_TEST_EQ( fv2_called, 0 ); + } + + { + fv2_called = 0; + + result r2 = result( in_place_error ) & fv2; + + BOOST_TEST( r2.has_error() ); + BOOST_TEST_EQ( fv2_called, 0 ); + } + return boost::report_errors(); }