diff --git a/include/boost/system/result.hpp b/include/boost/system/result.hpp index ebe2c04..cdfe85b 100644 --- a/include/boost/system/result.hpp +++ b/include/boost/system/result.hpp @@ -890,6 +890,8 @@ public: namespace detail { +// is_value_convertible_to + template struct is_value_convertible_to: std::is_convertible { }; @@ -901,6 +903,11 @@ template struct is_value_convertible_to: { }; +// is_result + +template struct is_result: std::false_type {}; +template struct is_result< result >: std::true_type {}; + } // namespace detail // result | value @@ -969,6 +976,59 @@ template()() ), + 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 *r; + } + else + { + return std::forward( f )(); + } +} + +template()() ), + class En1 = typename std::enable_if::value>::type, + class En2 = typename std::enable_if::value>::type +> + U operator|( result&& r, F&& f ) +{ + if( r ) + { + return *std::move( r ); + } + else + { + return std::forward( f )(); + } +} + +template()() ), + 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 {}; + } + else + { + return std::forward( f )(); + } +} + } // namespace system } // namespace boost diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bd013b6..c493aeb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -171,3 +171,4 @@ boost_test(TYPE run SOURCES result_or_value.cpp) boost_test(TYPE compile-fail SOURCES result_or_value_fail.cpp) 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) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 38efc9c..2d484fc 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -201,3 +201,4 @@ run result_or_value.cpp : : : $(CPP11) ; compile-fail result_or_value_fail.cpp : $(CPP11) ; compile-fail result_or_value_fail2.cpp : $(CPP11) ; run result_or_fn0v.cpp : : : $(CPP11) ; +run result_or_fn0r.cpp : : : $(CPP11) ; diff --git a/test/result_or_fn0r.cpp b/test/result_or_fn0r.cpp new file mode 100644 index 0000000..2ca5a21 --- /dev/null +++ b/test/result_or_fn0r.cpp @@ -0,0 +1,339 @@ +// 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 +{ +}; + +result fi() +{ + return 2; +} + +result fi2() +{ + return E(); +} + +result fy() +{ + return Y{ 2 }; +} + +result fy2() +{ + return E(); +} + +result fri() +{ + static int x = 2; + return x; +} + +result fri2() +{ + return E(); +} + +result fv() +{ + return {}; +} + +result fv2() +{ + return E(); +} + +int main() +{ + { + result r( 1 ); + + int x = r | fi | 3; + + BOOST_TEST_EQ( x, 1 ); + } + + { + result const r( 1 ); + + int x = r | fi | 3; + + BOOST_TEST_EQ( x, 1 ); + } + + { + int x = result( 1 ) | fi | 3; + + BOOST_TEST_EQ( x, 1 ); + } + + { + result r( 1 ); + + int x = r | fi2 | 3; + + BOOST_TEST_EQ( x, 1 ); + } + + { + result const r( 1 ); + + int x = r | fi2 | 3; + + BOOST_TEST_EQ( x, 1 ); + } + + { + int x = result( 1 ) | fi2 | 3; + + BOOST_TEST_EQ( x, 1 ); + } + + { + result r( in_place_error ); + + int x = r | fi | 3; + + BOOST_TEST_EQ( x, 2 ); + } + + { + result const r( in_place_error ); + + int x = r | fi | 3; + + BOOST_TEST_EQ( x, 2 ); + } + + { + int x = result( in_place_error ) | fi | 3; + + BOOST_TEST_EQ( x, 2 ); + } + + { + result r( in_place_error ); + + int x = r | fi2 | 3; + + BOOST_TEST_EQ( x, 3 ); + } + + { + result const r( in_place_error ); + + int x = r | fi2 | 3; + + BOOST_TEST_EQ( x, 3 ); + } + + { + int x = result( in_place_error ) | fi2 | 3; + + BOOST_TEST_EQ( x, 3 ); + } + + { + Y y = result( X{1} ) | fy | X{3}; + + BOOST_TEST_EQ( y.v_, 1 ); + } + + { + Y y = result( X{1} ) | fy2 | X{3}; + + BOOST_TEST_EQ( y.v_, 1 ); + } + + { + Y y = result( in_place_error ) | fy | X{3}; + + BOOST_TEST_EQ( y.v_, 2 ); + } + + { + Y y = result( in_place_error ) | fy2 | Y{3}; + + BOOST_TEST_EQ( y.v_, 3 ); + } + + { + int x1 = 1; + int x3 = 3; + + result r( x1 ); + + int& x = r | fri | x3; + + BOOST_TEST_EQ( &x, &x1 ); + } + + { + int x1 = 1; + int x3 = 3; + + result const r( x1 ); + + int& x = r | fri | x3; + + BOOST_TEST_EQ( &x, &x1 ); + } + + { + int x1 = 1; + int x3 = 3; + + int& x = result( x1 ) | fri | x3; + + BOOST_TEST_EQ( &x, &x1 ); + } + + { + int x1 = 1; + int x3 = 3; + + result r( x1 ); + + int& x = r | fri2 | x3; + + BOOST_TEST_EQ( &x, &x1 ); + } + + { + int x1 = 1; + int x3 = 3; + + result const r( x1 ); + + int& x = r | fri2 | x3; + + BOOST_TEST_EQ( &x, &x1 ); + } + + { + int x1 = 1; + int x3 = 3; + + int& x = result( x1 ) | fri2 | x3; + + BOOST_TEST_EQ( &x, &x1 ); + } + + { + int x3 = 3; + + result r( in_place_error ); + + int& x = r | fri | x3; + + BOOST_TEST_EQ( &x, &*fri() ); + } + + { + int x3 = 3; + + result const r( in_place_error ); + + int& x = r | fri | x3; + + BOOST_TEST_EQ( &x, &*fri() ); + } + + { + int x3 = 3; + + int& x = result( in_place_error ) | fri | x3; + + BOOST_TEST_EQ( &x, &*fri() ); + } + + { + int x3 = 3; + + result r( in_place_error ); + + int& x = r | fri2 | x3; + + BOOST_TEST_EQ( &x, &x3 ); + } + + { + int x3 = 3; + + result const r( in_place_error ); + + int& x = r | fri2 | x3; + + BOOST_TEST_EQ( &x, &x3 ); + } + + { + int x3 = 3; + + int& x = result( in_place_error ) | fri2 | x3; + + BOOST_TEST_EQ( &x, &x3 ); + } + + { + result r; + result r2 = r | fv; + + BOOST_TEST( r2.has_value() ); + } + + { + result r; + result r2 = r | fv2; + + BOOST_TEST( r2.has_value() ); + } + + { + result r( in_place_error ); + result r2 = r | fv; + + BOOST_TEST( r2.has_value() ); + } + + { + result r( in_place_error ); + result r2 = r | fv2; + + BOOST_TEST( r2.has_error() ); + } + + return boost::report_errors(); +}