diff --git a/include/boost/system/result.hpp b/include/boost/system/result.hpp index 2c6b381..c9b1b06 100644 --- a/include/boost/system/result.hpp +++ b/include/boost/system/result.hpp @@ -885,6 +885,56 @@ public: } }; +// operator| + +namespace detail +{ + +template struct is_value_convertible_to: std::is_convertible +{ +}; + +template struct is_value_convertible_to: + std::integral_constant::value && + std::is_convertible*, U*>::value> +{ +}; + +} // namespace detail + +// result | value + +template::value>::type +> + T operator|( result const& r, U&& u ) +{ + if( r ) + { + return *r; + } + else + { + return std::forward( u ); + } +} + +template::value>::type +> + T operator|( result&& r, U&& u ) +{ + if( r ) + { + return *std::move( r ); + } + else + { + return std::forward( u ); + } +} + } // namespace system } // namespace boost diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bc4b728..00d5ed8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -167,3 +167,6 @@ boost_test(TYPE run SOURCES result_error_move.cpp) boost_test(TYPE run SOURCES result_value_construct6.cpp) boost_test(TYPE run SOURCES result_value_construct7.cpp) boost_test(TYPE run SOURCES result_error_construct5.cpp) +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) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a27aec9..f13ab18 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -197,3 +197,6 @@ run result_error_move.cpp : : : $(CPP11) ; run result_value_construct6.cpp : : : $(CPP11) ; run result_value_construct7.cpp : : : $(CPP11) ; run result_error_construct5.cpp : : : $(CPP11) ; +run result_or_value.cpp : : : $(CPP11) ; +compile-fail result_or_value_fail.cpp : $(CPP11) ; +compile-fail result_or_value_fail2.cpp : $(CPP11) ; diff --git a/test/result_or_value.cpp b/test/result_or_value.cpp new file mode 100644 index 0000000..bf7f945 --- /dev/null +++ b/test/result_or_value.cpp @@ -0,0 +1,167 @@ +// 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 +{ +}; + +int main() +{ + { + result r( 1 ); + + int x = r | 2; + + BOOST_TEST_EQ( x, 1 ); + } + + { + result const r( 1 ); + + int x = r | 2; + + BOOST_TEST_EQ( x, 1 ); + } + + { + int x = result( 1 ) | 2; + + BOOST_TEST_EQ( x, 1 ); + } + + { + result r( in_place_error ); + + int x = r | 2; + + BOOST_TEST_EQ( x, 2 ); + } + + { + result const r( in_place_error ); + + int x = r | 2; + + BOOST_TEST_EQ( x, 2 ); + } + + { + int x = result( in_place_error ) | 2; + + BOOST_TEST_EQ( x, 2 ); + } + + { + Y y = result( in_place_value, 1 ) | Y{2}; + + BOOST_TEST_EQ( y.v_, 1 ); + } + + { + Y y = result( in_place_error ) | Y{2}; + + BOOST_TEST_EQ( y.v_, 2 ); + } + + { + Y y = result( in_place_value, 1 ) | X{2}; + + BOOST_TEST_EQ( y.v_, 1 ); + } + + { + Y y = result( in_place_error ) | X{2}; + + BOOST_TEST_EQ( y.v_, 2 ); + } + + { + int x1 = 1; + int x2 = 2; + + result r( x1 ); + + int& x = r | x2; + + BOOST_TEST_EQ( &x, &x1 ); + } + + { + int x1 = 1; + int x2 = 2; + + result const r( x1 ); + + int& x = r | x2; + + BOOST_TEST_EQ( &x, &x1 ); + } + + { + int x1 = 1; + int x2 = 2; + + int& x = result( x1 ) | x2; + + BOOST_TEST_EQ( &x, &x1 ); + } + + { + int x2 = 2; + + result r( in_place_error ); + + int& x = r | x2; + + BOOST_TEST_EQ( &x, &x2 ); + } + + { + int x2 = 2; + + result const r( in_place_error ); + + int& x = r | x2; + + BOOST_TEST_EQ( &x, &x2 ); + } + + { + int x2 = 2; + + int& x = result( in_place_error ) | x2; + + BOOST_TEST_EQ( &x, &x2 ); + } + + return boost::report_errors(); +} diff --git a/test/result_or_value_fail.cpp b/test/result_or_value_fail.cpp new file mode 100644 index 0000000..1e6a5cd --- /dev/null +++ b/test/result_or_value_fail.cpp @@ -0,0 +1,14 @@ +// Copyright 2017, 2021, 2022 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +using namespace boost::system; + +int main() +{ + int x = 1; + result r( x ); + r | 2; +} diff --git a/test/result_or_value_fail2.cpp b/test/result_or_value_fail2.cpp new file mode 100644 index 0000000..fca8fa1 --- /dev/null +++ b/test/result_or_value_fail2.cpp @@ -0,0 +1,13 @@ +// Copyright 2017, 2021, 2022 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +using namespace boost::system; + +int main() +{ + int x = 1; + result( x ) | 2; +}