From 54d3b253b13ee1a5c4dcf5c08765215d8d96e695 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 29 Oct 2023 20:57:29 +0200 Subject: [PATCH] Add operator&( result, unary-returning-result ) --- include/boost/system/result.hpp | 58 +++++- test/CMakeLists.txt | 1 + test/Jamfile.v2 | 1 + test/result_and_fn0r.cpp | 347 ++++++++++++++++++++++++++++++++ 4 files changed, 397 insertions(+), 10 deletions(-) create mode 100644 test/result_and_fn0r.cpp diff --git a/include/boost/system/result.hpp b/include/boost/system/result.hpp index 4490cb6..82dbe2a 100644 --- a/include/boost/system/result.hpp +++ b/include/boost/system/result.hpp @@ -915,7 +915,7 @@ template struct is_result< result >: std::true_type {}; template::value>::type > - T operator|( result const& r, U&& u ) +T operator|( result const& r, U&& u ) { if( r ) { @@ -930,7 +930,7 @@ template::value>::type > - T operator|( result&& r, U&& u ) +T operator|( result&& r, U&& u ) { if( r ) { @@ -948,7 +948,7 @@ template()() ), class En = typename std::enable_if::value>::type > - T operator|( result const& r, F&& f ) +T operator|( result const& r, F&& f ) { if( r ) { @@ -964,7 +964,7 @@ template()() ), class En = typename std::enable_if::value>::type > - T operator|( result&& r, F&& f ) +T operator|( result&& r, F&& f ) { if( r ) { @@ -983,7 +983,7 @@ template::value>::type, class En2 = typename std::enable_if::value>::type > - U operator|( result const& r, F&& f ) +U operator|( result const& r, F&& f ) { if( r ) { @@ -1000,7 +1000,7 @@ template::value>::type, class En2 = typename std::enable_if::value>::type > - U operator|( result&& r, F&& f ) +U operator|( result&& r, F&& f ) { if( r ) { @@ -1017,7 +1017,7 @@ template::value>::type, class En2 = typename std::enable_if::value>::type > - U operator|( result const& r, F&& f ) +U operator|( result const& r, F&& f ) { if( r ) { @@ -1034,7 +1034,7 @@ template::value>::type, class En2 = typename std::enable_if::value>::type > - U operator|( result&& r, F&& f ) +U operator|( result&& r, F&& f ) { if( r ) { @@ -1046,13 +1046,15 @@ template()( std::declval() ) ), class En = typename std::enable_if::value>::type > - result operator&( result const& r, F&& f ) +result operator&( result const& r, F&& f ) { if( r ) { @@ -1068,7 +1070,43 @@ template()( std::declval() ) ), class En = typename std::enable_if::value>::type > - result operator&( result&& r, F&& f ) +result operator&( result&& r, F&& f ) +{ + if( r ) + { + return std::forward( f )( *std::move( r ) ); + } + else + { + return r.error(); + } +} + +// result & unary-returning-result + +template()( std::declval() ) ), + class En1 = typename std::enable_if::value>::type, + class En2 = typename std::enable_if::value>::type +> +U operator&( result const& r, F&& f ) +{ + if( r ) + { + return std::forward( f )( *r ); + } + else + { + return r.error(); + } +} + +template()( std::declval() ) ), + class En1 = typename std::enable_if::value>::type, + class En2 = typename std::enable_if::value>::type +> +U operator&( result&& r, F&& f ) { if( r ) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6d4e2b3..12d3064 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -173,3 +173,4 @@ boost_test(TYPE compile-fail SOURCES result_or_value_fail2.cpp) boost_test(TYPE run SOURCES result_or_fn0v.cpp) boost_test(TYPE run SOURCES result_or_fn0r.cpp) boost_test(TYPE run SOURCES result_and_fn0v.cpp) +boost_test(TYPE run SOURCES result_and_fn0r.cpp) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1864c07..d594d7d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -203,3 +203,4 @@ compile-fail result_or_value_fail2.cpp : $(CPP11) ; run result_or_fn0v.cpp : : : $(CPP11) ; run result_or_fn0r.cpp : : : $(CPP11) ; run result_and_fn0v.cpp : : : $(CPP11) ; +run result_and_fn0r.cpp : : : $(CPP11) ; diff --git a/test/result_and_fn0r.cpp b/test/result_and_fn0r.cpp new file mode 100644 index 0000000..249779a --- /dev/null +++ b/test/result_and_fn0r.cpp @@ -0,0 +1,347 @@ +// Copyright 2017, 2021, 2022 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +using namespace boost::system; + +struct X +{ + int v_; +}; + +struct Y +{ + int v_; + + explicit Y( int v ): v_( v ) {} + Y( X x ): v_( x.v_) {} + + Y( Y const& ) = delete; + Y& operator=( Y const& ) = delete; + + Y( Y&& r ): v_( r.v_ ) + { + r.v_ = 0; + } + + Y& operator=( Y&& ) = delete; +}; + +struct E +{ +}; + +struct E2 +{ + E2() {} + E2( E ) {} +}; + +result fi( int x ) +{ + return 2 * x + 1; +} + +result fi2( int ) +{ + return E2(); +} + +result fi3( int ) +{ + return {}; +} + +result fy( Y y ) +{ + return X{ 2 * y.v_ + 1 }; +} + +result fy2( Y ) +{ + return E2(); +} + +result fy3( Y ) +{ + return {}; +} + +result fri( int& x ) +{ + return x * 2 + 1; +} + +result fri2( int& ) +{ + return E2(); +} + +result fri3( int& ) +{ + return {}; +} + +int main() +{ + { + result r( 1 ); + + { + result r2 = r & fi; + BOOST_TEST( r2.has_value() ) && BOOST_TEST_EQ( *r2, 3 ); + } + + { + result r2 = r & fi2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fi3; + BOOST_TEST( r2.has_value() ); + } + } + + { + result const r( 1 ); + + { + result r2 = r & fi; + BOOST_TEST( r2.has_value() ) && BOOST_TEST_EQ( *r2, 3 ); + } + + { + result r2 = r & fi2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fi3; + BOOST_TEST( r2.has_value() ); + } + } + + { + result r2 = result( 1 ) & fi; + BOOST_TEST( r2.has_value() ) && BOOST_TEST_EQ( *r2, 3 ); + } + + { + result r2 = result( 1 ) & fi2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = result( 1 ) & fi3; + BOOST_TEST( r2.has_value() ); + } + + { + result r( in_place_error ); + + { + result r2 = r & fi; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fi2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fi3; + BOOST_TEST( r2.has_error() ); + } + } + + { + result const r( in_place_error ); + + { + result r2 = r & fi; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fi2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fi3; + BOOST_TEST( r2.has_error() ); + } + } + + { + result r2 = result( in_place_error ) & fi; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = result( in_place_error ) & fi2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = result( in_place_error ) & fi3; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = result( in_place_value, 1 ) & fy; + + BOOST_TEST( r2.has_value() ) && BOOST_TEST_EQ( r2->v_, 3 ); + } + + { + result r2 = result( in_place_value, 1 ) & fy2; + + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = result( in_place_value, 1 ) & fy3; + + BOOST_TEST( r2.has_value() ); + } + + { + result r2 = result( in_place_error ) & fy; + + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = result( in_place_error ) & fy2; + + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = result( in_place_error ) & fy3; + + BOOST_TEST( r2.has_error() ); + } + + { + int x1 = 1; + result r( x1 ); + + { + result r2 = r & fri; + BOOST_TEST( r2.has_value() ) && BOOST_TEST_EQ( *r2, 3 ); + } + + { + result r2 = r & fri2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fri3; + BOOST_TEST( r2.has_value() ); + } + } + + { + int x1 = 1; + result const r( x1 ); + + { + result r2 = r & fri; + BOOST_TEST( r2.has_value() ) && BOOST_TEST_EQ( *r2, 3 ); + } + + { + result r2 = r & fri2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fri3; + BOOST_TEST( r2.has_value() ); + } + } + + { + int x1 = 1; + + result r2 = result( x1 ) & fri; + BOOST_TEST( r2.has_value() ) && BOOST_TEST_EQ( *r2, 3 ); + } + + { + int x1 = 1; + + result r2 = result( x1 ) & fri2; + BOOST_TEST( r2.has_error() ); + } + + { + int x1 = 1; + + result r2 = result( x1 ) & fri3; + BOOST_TEST( r2.has_value() ); + } + + { + result r( in_place_error ); + + { + result r2 = r & fri; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fri2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fri3; + BOOST_TEST( r2.has_error() ); + } + } + + { + result const r( in_place_error ); + + { + result r2 = r & fri; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fri2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = r & fri3; + BOOST_TEST( r2.has_error() ); + } + } + + { + result r2 = result( in_place_error ) & fri; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = result( in_place_error ) & fri2; + BOOST_TEST( r2.has_error() ); + } + + { + result r2 = result( in_place_error ) & fri3; + BOOST_TEST( r2.has_error() ); + } + + return boost::report_errors(); +}