From 4200b00973516f0a374a6864c3f98184582b1296 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 18 Jun 2022 17:58:24 +0300 Subject: [PATCH] Add converting constructor to `result` (refs #82) --- include/boost/system/result.hpp | 37 ++++++ test/CMakeLists.txt | 1 + test/Jamfile.v2 | 1 + test/result_convert_construct.cpp | 202 ++++++++++++++++++++++++++++++ 4 files changed, 241 insertions(+) create mode 100644 test/result_convert_construct.cpp diff --git a/include/boost/system/result.hpp b/include/boost/system/result.hpp index 26baa6d..8ff55fb 100644 --- a/include/boost/system/result.hpp +++ b/include/boost/system/result.hpp @@ -174,6 +174,43 @@ public: { } + // converting + template::value && + std::is_convertible::value + >::type> + BOOST_CXX14_CONSTEXPR result( result const& r2 ) + noexcept( + std::is_nothrow_constructible::value && + std::is_nothrow_constructible::value && + std::is_nothrow_default_constructible::value && + std::is_nothrow_copy_constructible::value ) + : v_( in_place_error, r2.error() ) + { + if( r2 ) + { + v_.template emplace<0>( *r2 ); + } + } + + template::value && + std::is_convertible::value + >::type> + BOOST_CXX14_CONSTEXPR result( result&& r2 ) + noexcept( + std::is_nothrow_constructible::value && + std::is_nothrow_constructible::value && + std::is_nothrow_default_constructible::value && + std::is_nothrow_copy_constructible::value ) + : v_( in_place_error, r2.error() ) + { + if( r2 ) + { + v_.template emplace<0>( std::move( *r2 ) ); + } + } + // queries constexpr bool has_value() const noexcept diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9c09d7d..3d08049 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -142,3 +142,4 @@ boost_test(TYPE run SOURCES result_eq.cpp) boost_test(TYPE run SOURCES result_range_for.cpp) boost_test(TYPE run SOURCES result_value_construct2.cpp) boost_test(TYPE run SOURCES result_error_construct2.cpp) +boost_test(TYPE run SOURCES result_convert_construct.cpp) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 684992d..b67088d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -169,3 +169,4 @@ run result_range_for.cpp : : : $(CPP11) ; run result_value_construct2.cpp : : : $(CPP11) ; run result_error_construct2.cpp : : : $(CPP11) ; run result_errc_construct.cpp : : : $(CPP11) ; +run result_convert_construct.cpp : : : $(CPP11) ; diff --git a/test/result_convert_construct.cpp b/test/result_convert_construct.cpp new file mode 100644 index 0000000..be6faad --- /dev/null +++ b/test/result_convert_construct.cpp @@ -0,0 +1,202 @@ +// 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 +#include + +using namespace boost::system; + +struct X +{ + static int instances; + + int v_; + + X(): v_() { ++instances; } + + X( int v ): v_( v ) { ++instances; } + + X( X const& r ): v_( r.v_ ) { ++instances; } + + X& operator=( X const& ) = delete; + + ~X() { --instances; } +}; + +bool operator==( X const & x1, X const & x2 ) +{ + return x1.v_ == x2.v_; +} + +std::ostream& operator<<( std::ostream& os, X const & x ) +{ + os << "X:" << x.v_; + return os; +} + +int X::instances = 0; + +int main() +{ + { + result r( 5 ); + result r2 = r; + + BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 5 ); + } + + { + result const r( 6 ); + result r2 = r; + + BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 6 ); + } + + { + result r2 = result( 7 ); + + BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 7 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); + + { + result r( 5 ); + result r2 = r; + + BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 5 ); + BOOST_TEST_EQ( X::instances, 1 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); + + { + result const r( 6 ); + result r2 = r; + + BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 6 ); + BOOST_TEST_EQ( X::instances, 1 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); + + { + result r2 = result( 7 ); + + BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 7 ); + BOOST_TEST_EQ( X::instances, 1 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); + + { + auto ec = make_error_code( errc::invalid_argument ); + + result r( ec ); + result r2 = r; + + BOOST_TEST( !r2 ); + BOOST_TEST_EQ( r2.error(), ec ); + } + + { + auto ec = make_error_code( errc::invalid_argument ); + + result r( ec ); + result r2 = r; + + BOOST_TEST( !r2 ); + BOOST_TEST_EQ( r2.error(), ec ); + } + + { + auto ec = make_error_code( errc::invalid_argument ); + + result r2 = result( ec ); + + BOOST_TEST( !r2 ); + BOOST_TEST_EQ( r2.error(), ec ); + } + + BOOST_TEST_EQ( X::instances, 0 ); + + { + result r( "test" ); + result r2 = r; + + BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, std::string( "test" ) ); + BOOST_TEST_EQ( X::instances, 0 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); + + { + result const r( "test" ); + result r2 = r; + + BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, std::string( "test" ) ); + BOOST_TEST_EQ( X::instances, 0 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); + + { + result r2 = result( "test" ); + + BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, std::string( "test" ) ); + BOOST_TEST_EQ( X::instances, 0 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); + + { + result r( 5 ); + result r2 = r; + + BOOST_TEST( !r2 ); + BOOST_TEST_EQ( r2.error(), X(5) ); + BOOST_TEST_EQ( X::instances, 1 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); + + { + result const r( 6 ); + result r2 = r; + + BOOST_TEST( !r2 ); + BOOST_TEST_EQ( r2.error(), X(6) ); + BOOST_TEST_EQ( X::instances, 1 ); + } + + { + result r2 = result( 7 ); + + BOOST_TEST( !r2 ); + BOOST_TEST_EQ( r2.error(), X(7) ); + BOOST_TEST_EQ( X::instances, 1 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); + + { + BOOST_TEST_TRAIT_TRUE((std::is_constructible, result>)); + BOOST_TEST_TRAIT_TRUE((std::is_convertible, result>)); + + BOOST_TEST_TRAIT_FALSE((std::is_constructible, result>)); + BOOST_TEST_TRAIT_FALSE((std::is_convertible, result>)); + + BOOST_TEST_TRAIT_FALSE((std::is_constructible, result>)); + BOOST_TEST_TRAIT_FALSE((std::is_convertible, result>)); + + BOOST_TEST_TRAIT_FALSE((std::is_constructible, result>)); + BOOST_TEST_TRAIT_FALSE((std::is_convertible, result>)); + + BOOST_TEST_TRAIT_FALSE((std::is_constructible, result>)); + BOOST_TEST_TRAIT_FALSE((std::is_convertible, result>)); + } + + return boost::report_errors(); +}