Add <boost/system/result.hpp>

This commit is contained in:
Peter Dimov
2021-09-16 18:47:05 +03:00
parent 6156076dab
commit fd852c675e
13 changed files with 2864 additions and 1 deletions

View File

@ -0,0 +1,341 @@
#ifndef BOOST_RESULT_RESULT_HPP_INCLUDED
#define BOOST_RESULT_RESULT_HPP_INCLUDED
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/variant2/variant.hpp>
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <system_error>
#include <type_traits>
#include <utility>
#include <iosfwd>
//
namespace boost
{
namespace result
{
// throw_exception_from_error_code
BOOST_NORETURN void throw_exception_from_error_code( std::error_code const & e )
{
boost::throw_exception( std::system_error( e ) );
}
// in_place_*
using in_place_value_t = variant2::in_place_index_t<0>;
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{};
// result
template<class T, class E = std::error_code> class result
{
private:
variant2::variant<T, E> v_;
public:
// constructors
// default
template<class En2 = void, class En = typename std::enable_if<
std::is_void<En2>::value &&
std::is_default_constructible<T>::value
>::type>
constexpr result()
noexcept( std::is_nothrow_default_constructible<T>::value )
: v_( in_place_value )
{
}
// explicit, value
template<class A, class En = typename std::enable_if<
std::is_constructible<T, A>::value &&
!std::is_convertible<A, T>::value &&
!std::is_constructible<E, A>::value
>::type>
explicit constexpr result( A&& a )
noexcept( std::is_nothrow_constructible<T, A>::value )
: v_( in_place_value, std::forward<A>(a) )
{
}
// explicit, error
template<class A, class En2 = void, class En = typename std::enable_if<
std::is_constructible<E, A>::value &&
!std::is_convertible<A, E>::value &&
!std::is_constructible<T, A>::value
>::type>
explicit constexpr result( A&& a )
noexcept( std::is_nothrow_constructible<E, A>::value )
: v_( in_place_error, std::forward<A>(a) )
{
}
// implicit, value
template<class A, class En2 = void, class En3 = void, class En = typename std::enable_if<
std::is_convertible<A, T>::value &&
!std::is_constructible<E, A>::value
>::type>
constexpr result( A&& a )
noexcept( std::is_nothrow_constructible<T, A>::value )
: v_( in_place_value, std::forward<A>(a) )
{
}
// implicit, error
template<class A, class En2 = void, class En3 = void, class En4 = void, class En = typename std::enable_if<
std::is_convertible<A, E>::value &&
!std::is_constructible<T, A>::value
>::type>
constexpr result( A&& a )
noexcept( std::is_nothrow_constructible<E, A>::value )
: v_( in_place_error, std::forward<A>(a) )
{
}
// more than one arg, value
template<class... A, class En = typename std::enable_if<
std::is_constructible<T, A...>::value &&
!std::is_constructible<E, A...>::value &&
sizeof...(A) >= 2
>::type>
constexpr result( A&&... a )
noexcept( std::is_nothrow_constructible<T, A...>::value )
: v_( in_place_value, std::forward<A>(a)... )
{
}
// more than one arg, error
template<class... A, class En2 = void, class En = typename std::enable_if<
!std::is_constructible<T, A...>::value &&
std::is_constructible<E, A...>::value &&
sizeof...(A) >= 2
>::type>
constexpr result( A&&... a )
noexcept( std::is_nothrow_constructible<E, A...>::value )
: v_( in_place_error, std::forward<A>(a)... )
{
}
// tagged, value
template<class... A, class En = typename std::enable_if<
std::is_constructible<T, A...>::value
>::type>
constexpr result( in_place_value_t, A&&... a )
noexcept( std::is_nothrow_constructible<T, A...>::value )
: v_( in_place_value, std::forward<A>(a)... )
{
}
// tagged, error
template<class... A, class En = typename std::enable_if<
std::is_constructible<E, A...>::value
>::type>
constexpr result( in_place_error_t, A&&... a )
noexcept( std::is_nothrow_constructible<E, A...>::value )
: v_( in_place_error, std::forward<A>(a)... )
{
}
// queries
constexpr bool has_value() const noexcept
{
return v_.index() == 0;
}
constexpr bool has_error() const noexcept
{
return v_.index() != 0;
}
constexpr explicit operator bool() const noexcept
{
return v_.index() == 0;
}
// checked value access
#if defined( BOOST_NO_CXX11_REF_QUALIFIERS )
BOOST_CXX14_CONSTEXPR T value() const
{
if( has_value() )
{
return *variant2::get_if<0>( &v_ );
}
else
{
throw_exception_from_error_code( *variant2::get_if<1>( &v_ ) );
}
}
#else
BOOST_CXX14_CONSTEXPR T& value() &
{
if( has_value() )
{
return *variant2::get_if<0>( &v_ );
}
else
{
throw_exception_from_error_code( *variant2::get_if<1>( &v_ ) );
}
}
BOOST_CXX14_CONSTEXPR T const& value() const&
{
if( has_value() )
{
return *variant2::get_if<0>( &v_ );
}
else
{
throw_exception_from_error_code( *variant2::get_if<1>( &v_ ) );
}
}
BOOST_CXX14_CONSTEXPR T&& value() &&
{
return std::move( value() );
}
BOOST_CXX14_CONSTEXPR T const&& value() const&&
{
return std::move( value() );
}
#endif
// unchecked value access
BOOST_CXX14_CONSTEXPR T* operator->() noexcept
{
return variant2::get_if<0>( &v_ );
}
BOOST_CXX14_CONSTEXPR T const* operator->() const noexcept
{
return variant2::get_if<0>( &v_ );
}
#if defined( BOOST_NO_CXX11_REF_QUALIFIERS )
BOOST_CXX14_CONSTEXPR T& operator*() noexcept
{
T* p = operator->();
BOOST_ASSERT( p != 0 );
return *p;
}
BOOST_CXX14_CONSTEXPR T const& operator*() const noexcept
{
T const* p = operator->();
BOOST_ASSERT( p != 0 );
return *p;
}
#else
BOOST_CXX14_CONSTEXPR T& operator*() & noexcept
{
T* p = operator->();
BOOST_ASSERT( p != 0 );
return *p;
}
BOOST_CXX14_CONSTEXPR T const& operator*() const & noexcept
{
T const* p = operator->();
BOOST_ASSERT( p != 0 );
return *p;
}
BOOST_CXX14_CONSTEXPR T&& operator*() && noexcept
{
return std::move(**this);
}
BOOST_CXX14_CONSTEXPR T const&& operator*() const && noexcept
{
return std::move(**this);
}
#endif
// error access
BOOST_CXX14_CONSTEXPR E error() const
noexcept( std::is_nothrow_default_constructible<E>::value && std::is_nothrow_copy_constructible<E>::value )
{
E const * p = variant2::get_if<1>( &v_ );
return p? *p: E();
}
// swap
BOOST_CXX14_CONSTEXPR void swap( result& r )
noexcept( noexcept( v_.swap( r.v_ ) ) )
{
v_.swap( r.v_ );
}
friend BOOST_CXX14_CONSTEXPR void swap( result & r1, result & r2 )
noexcept( noexcept( r1.swap( r2 ) ) )
{
r1.swap( r2 );
}
// equality
friend constexpr bool operator==( result const & r1, result const & r2 )
noexcept( noexcept( r1.v_ == r2.v_ ) )
{
return r1.v_ == r2.v_;
}
friend constexpr bool operator!=( result const & r1, result const & r2 )
noexcept( noexcept( !( r1 == r2 ) ) )
{
return !( r1 == r2 );
}
};
template<class Ch, class Tr, class T, class E> std::basic_ostream<Ch, Tr>& operator<<( std::basic_ostream<Ch, Tr>& os, result<T, E> const & r )
{
if( r.has_value() )
{
os << "value:" << *r;
}
else
{
os << "error:" << r.error();
}
return os;
}
} // namespace result
} // namespace boost
#endif // #ifndef BOOST_RESULT_RESULT_HPP_INCLUDED

View File

@ -1,7 +1,7 @@
# Boost System Library test Jamfile
# Copyright Beman Dawes 2003, 2006
# Copyright 2017-2019 Peter Dimov
# Copyright 2017-2021 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt
@ -10,6 +10,18 @@
import testing ;
project
: default-build
<warnings>extra
: requirements
<toolset>msvc:<warnings-as-errors>on
<toolset>gcc:<warnings-as-errors>on
<toolset>clang:<warnings-as-errors>on
;
rule system-run ( sources + )
{
local result ;
@ -110,3 +122,21 @@ run std_interop_test8.cpp ;
run std_interop_test9.cpp ;
run ec_location_test.cpp ;
# result
import ../../config/checks/config : requires ;
CPP11 = [ requires cxx11_variadic_templates cxx11_template_aliases cxx11_decltype cxx11_constexpr cxx11_noexcept ] ;
run result_default_construct.cpp : : : $(CPP11) ;
run result_value_construct.cpp : : : $(CPP11) ;
run result_error_construct.cpp : : : $(CPP11) ;
run result_copy_construct.cpp : : : $(CPP11) ;
run result_move_construct.cpp : : : $(CPP11) ;
run result_copy_assign.cpp : : : $(CPP11) ;
run result_move_assign.cpp : : : $(CPP11) ;
run result_value_access.cpp : : : $(CPP11) ;
run result_error_access.cpp : : : $(CPP11) ;
run result_swap.cpp : : : $(CPP11) <toolset>gcc-10:<cxxflags>"-Wno-maybe-uninitialized" ;
run result_eq.cpp : : : $(CPP11) ;

605
test/result_copy_assign.cpp Normal file
View File

@ -0,0 +1,605 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <system_error>
#include <iosfwd>
#include <cerrno>
using namespace boost::result;
struct X
{
static int instances;
int v_;
explicit X( int v = 0 ): v_( v ) { ++instances; }
X( X const& r ): v_( r.v_ ) { ++instances; }
X& operator=( X const& ) = default;
~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;
struct Y
{
static int instances;
int v_;
explicit Y( int v = 0 ): v_( v ) { ++instances; }
Y( Y const& r ) noexcept: v_( r.v_ ) { ++instances; }
Y& operator=( Y const& ) = default;
~Y() { --instances; }
};
bool operator==( Y const & y1, Y const & y2 )
{
return y1.v_ == y2.v_;
}
std::ostream& operator<<( std::ostream& os, Y const & y )
{
os << "Y:" << y.v_;
return os;
}
int Y::instances = 0;
int main()
{
// default-initialized lhs
{
result<int> r;
result<int> r2;
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
result<int> r;
result<int> r2( 1 );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
result<int> r;
result<int> r2( ENOENT, std::generic_category() );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
result<int> const r;
result<int> r2;
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
result<int> const r;
result<int> r2( 1 );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
result<int> const r;
result<int> r2( ENOENT, std::generic_category() );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r;
result<X> r2;
BOOST_TEST_EQ( X::instances, 2 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r;
result<X> r2( 1 );
BOOST_TEST_EQ( X::instances, 2 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r;
result<X> r2( ENOENT, std::generic_category() );
BOOST_TEST_EQ( X::instances, 1 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> const r;
result<X> r2;
BOOST_TEST_EQ( X::instances, 2 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> const r;
result<X> r2( 1 );
BOOST_TEST_EQ( X::instances, 2 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> const r;
result<X> r2( ENOENT, std::generic_category() );
BOOST_TEST_EQ( X::instances, 1 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
// value lhs
{
result<int> r( 0 );
result<int> r2;
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
result<int> r( 0 );
result<int> r2( 1 );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
result<int> r( 0 );
result<int> r2( ENOENT, std::generic_category() );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
result<int> const r( 0 );
result<int> r2;
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
result<int> const r( 0 );
result<int> r2( 1 );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
result<int> const r( 0 );
result<int> r2( ENOENT, std::generic_category() );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1 );
result<X> r2;
BOOST_TEST_EQ( X::instances, 2 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1 );
result<X> r2( 2 );
BOOST_TEST_EQ( X::instances, 2 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1 );
result<X> r2( ENOENT, std::generic_category() );
BOOST_TEST_EQ( X::instances, 1 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> const r( 1 );
result<X> r2;
BOOST_TEST_EQ( X::instances, 2 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> const r( 1 );
result<X> r2( 2 );
BOOST_TEST_EQ( X::instances, 2 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> const r( 1 );
result<X> r2( ENOENT, std::generic_category() );
BOOST_TEST_EQ( X::instances, 1 );
r2 = r;
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
// error lhs
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
result<int> r2;
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
result<int> r2( 1 );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
result<int> r2( ENOENT, std::generic_category() );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> const r( ec );
result<int> r2;
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> const r( ec );
result<int> r2( 1 );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> const r( ec );
result<int> r2( ENOENT, std::generic_category() );
r2 = r;
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<X> r( ec );
result<X> r2;
BOOST_TEST_EQ( X::instances, 1 );
r2 = r;
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<X> r( ec );
result<X> r2( 1 );
BOOST_TEST_EQ( X::instances, 1 );
r2 = r;
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<X> r( ec );
result<X> r2( ENOENT, std::generic_category() );
BOOST_TEST_EQ( X::instances, 0 );
r2 = r;
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<X> const r( ec );
result<X> r2;
BOOST_TEST_EQ( X::instances, 1 );
r2 = r;
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<X> const r( ec );
result<X> r2( 1 );
BOOST_TEST_EQ( X::instances, 1 );
r2 = r;
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<X> const r( ec );
result<X> r2( ENOENT, std::generic_category() );
BOOST_TEST_EQ( X::instances, 0 );
r2 = r;
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
//
BOOST_TEST_EQ( Y::instances, 0 );
{
result<std::string, Y> r( 1 );
result<std::string, Y> r2( 2 );
BOOST_TEST_EQ( Y::instances, 2 );
r2 = r;
BOOST_TEST_EQ( Y::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( Y::instances, 0 );
{
result<std::string, Y> r( 1 );
result<std::string, Y> r2( "str" );
BOOST_TEST_EQ( Y::instances, 1 );
r2 = r;
BOOST_TEST_EQ( Y::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( Y::instances, 0 );
{
result<std::string, Y> const r( 1 );
result<std::string, Y> r2( 2 );
BOOST_TEST_EQ( Y::instances, 2 );
r2 = r;
BOOST_TEST_EQ( Y::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( Y::instances, 0 );
{
result<std::string, Y> const r( 1 );
result<std::string, Y> r2( "str" );
BOOST_TEST_EQ( Y::instances, 1 );
r2 = r;
BOOST_TEST_EQ( Y::instances, 2 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( Y::instances, 0 );
return boost::report_errors();
}

View File

@ -0,0 +1,149 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
using namespace boost::result;
struct X
{
static int instances;
int v_;
X(): v_() { ++instances; }
explicit X( int v ): v_( v ) { ++instances; }
X( int v1, int v2 ): v_( v1+v2 ) { ++instances; }
X( int v1, int v2, int v3 ): v_( v1+v2+v3 ) { ++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<int> r;
result<int> r2( r );
BOOST_TEST_EQ( r, r2 );
}
{
result<int> const r;
result<int> r2( r );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r;
result<X> r2( r );
BOOST_TEST_EQ( r, r2 );
BOOST_TEST_EQ( X::instances, 2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<int> r( 1 );
result<int> r2( r );
BOOST_TEST_EQ( r, r2 );
}
{
result<int> const r( 1 );
result<int> r2( r );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1 );
result<X> r2( r );
BOOST_TEST_EQ( r, r2 );
BOOST_TEST_EQ( X::instances, 2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> const r( 1 );
result<X> r2( r );
BOOST_TEST_EQ( r, r2 );
BOOST_TEST_EQ( X::instances, 2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
result<int> r2( r );
BOOST_TEST_EQ( r, r2 );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> const r( ec );
result<int> r2( r );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<std::string, X> r( 1 );
result<std::string, X> r2( r );
BOOST_TEST_EQ( r, r2 );
BOOST_TEST_EQ( X::instances, 2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<std::string, X> const r( 1 );
result<std::string, X> r2( r );
BOOST_TEST_EQ( r, r2 );
BOOST_TEST_EQ( X::instances, 2 );
}
BOOST_TEST_EQ( X::instances, 0 );
return boost::report_errors();
}

View File

@ -0,0 +1,34 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
using namespace boost::result;
struct X
{
};
int main()
{
{
result<int> r;
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.value(), 0 );
}
{
result<X> r;
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
}
return boost::report_errors();
}

138
test/result_eq.cpp Normal file
View File

@ -0,0 +1,138 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <system_error>
#include <iosfwd>
#include <cerrno>
using namespace boost::result;
struct X
{
static int instances;
int v_;
explicit X( int v ): v_( v ) { ++instances; }
X( X const& r ) = delete;
X( X&& r ): v_( r.v_ ) { r.v_ = 0; ++instances; }
X& operator=( X const& ) = delete;
X& operator=( X&& r )
{
v_ = r.v_;
r.v_ = 0;
return *this;
}
~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;
struct Y
{
static int instances;
int v_;
explicit Y( int v = 0 ): v_( v ) { ++instances; }
Y( Y const& r ) noexcept: v_( r.v_ ) { ++instances; }
Y( Y&& r ) noexcept: v_( r.v_ ) { r.v_ = 0; ++instances; }
Y& operator=( Y const& ) = default;
Y& operator=( Y&& r )
{
v_ = r.v_;
r.v_ = 0;
return *this;
}
~Y() { --instances; }
};
bool operator==( Y const & y1, Y const & y2 )
{
return y1.v_ == y2.v_;
}
std::ostream& operator<<( std::ostream& os, Y const & y )
{
os << "Y:" << y.v_;
return os;
}
int Y::instances = 0;
int main()
{
{
result<int> r1( 1 );
result<int> r2( 2 );
BOOST_TEST_EQ( r1, r1 );
BOOST_TEST_NE( r1, r2 );
}
{
result<int> r1( 1, std::generic_category() );
result<int> r2( 2, std::generic_category() );
BOOST_TEST_EQ( r1, r1 );
BOOST_TEST_NE( r1, r2 );
}
{
result<int> r1( 1 );
result<int> r2( 2, std::generic_category() );
BOOST_TEST_EQ( r1, r1 );
BOOST_TEST_NE( r1, r2 );
}
{
result<X, Y> r1( in_place_value, 1 );
result<X, Y> r2( in_place_value, 2 );
BOOST_TEST_EQ( r1, r1 );
BOOST_TEST_NE( r1, r2 );
}
{
result<X, Y> r1( in_place_error, 1 );
result<X, Y> r2( in_place_error, 2 );
BOOST_TEST_EQ( r1, r1 );
BOOST_TEST_NE( r1, r2 );
}
{
result<X, Y> r1( in_place_value, 1 );
result<X, Y> r2( in_place_error, 2 );
BOOST_TEST_EQ( r1, r1 );
BOOST_TEST_NE( r1, r2 );
}
return boost::report_errors();
}

View File

@ -0,0 +1,156 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <string>
using namespace boost::result;
struct X
{
int v_;
explicit X( int v = 0 ): v_( v ) {}
X( X const& ) = default;
X& operator=( X const& ) = delete;
};
int main()
{
{
result<int> r;
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.error(), std::error_code() );
}
{
result<int> const r;
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.error(), std::error_code() );
}
{
BOOST_TEST( result<int>().has_value() );
BOOST_TEST( !result<int>().has_error() );
BOOST_TEST_EQ( result<int>().error(), std::error_code() );
}
{
result<int> r( 1 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.error(), std::error_code() );
}
{
result<int> const r( 1 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.error(), std::error_code() );
}
{
BOOST_TEST( result<int>( 1 ).has_value() );
BOOST_TEST( !result<int>( 1 ).has_error() );
BOOST_TEST_EQ( result<int>( 1 ).error(), std::error_code() );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error(), ec );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> const r( ec );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error(), ec );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
BOOST_TEST( !result<int>( ec ).has_value() );
BOOST_TEST( result<int>( ec ).has_error() );
BOOST_TEST_EQ( result<int>( ec ).error(), ec );
}
{
result<std::string, X> r( 1 );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error().v_, 1 );
}
{
result<std::string, X> const r( 1 );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error().v_, 1 );
}
{
BOOST_TEST(( !result<std::string, X>( 1 ).has_value() ));
BOOST_TEST(( result<std::string, X>( 1 ).has_error() ));
BOOST_TEST_EQ( (result<std::string, X>( 1 ).error().v_), 1 );
}
{
result<std::string, X> r( "s" );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.error().v_, 0 );
}
{
result<std::string, X> const r( "s" );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.error().v_, 0 );
}
{
BOOST_TEST(( result<std::string, X>( "s" ).has_value() ));
BOOST_TEST(( !result<std::string, X>( "s" ).has_error() ));
BOOST_TEST_EQ( (result<std::string, X>( "s" ).error().v_), 0 );
}
return boost::report_errors();
}

View File

@ -0,0 +1,155 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <system_error>
#include <string>
#include <cerrno>
using namespace boost::result;
struct X
{
static int instances;
int v_;
X(): v_() { ++instances; }
explicit X( int v ): v_( v ) { ++instances; }
X( int v1, int v2 ): v_( v1+v2 ) { ++instances; }
X( int v1, int v2, int v3 ): v_( v1+v2+v3 ) { ++instances; }
X( X const& r ): v_( r.v_ ) { ++instances; }
X& operator=( X const& ) = delete;
~X() { --instances; }
};
int X::instances = 0;
int main()
{
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error(), ec );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r = ec;
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error(), ec );
}
{
result<int> r( EINVAL, std::generic_category() );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error(), std::error_code( EINVAL, std::generic_category() ) );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<std::error_code> r( in_place_error, ec );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error(), ec );
}
{
result<std::error_code> r( in_place_error, EINVAL, std::generic_category() );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error(), std::error_code( EINVAL, std::generic_category() ) );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<std::string, X> r( 1 );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error().v_, 1 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<int, X> r( 1, 2 );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error().v_, 1+2 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<int, X> r( 1, 2, 3 );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error().v_, 1+2+3 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X, X> r( in_place_error, 1 );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error().v_, 1 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
BOOST_TEST_TRAIT_TRUE((std::is_constructible<result<int>, std::error_code>));
BOOST_TEST_TRAIT_TRUE((std::is_convertible<std::error_code, result<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_constructible<result<std::string, X>, int>));
BOOST_TEST_TRAIT_FALSE((std::is_convertible<int, result<std::string, X>>));
BOOST_TEST_TRAIT_FALSE((std::is_constructible<result<int, X>, int>));
BOOST_TEST_TRAIT_FALSE((std::is_convertible<int, result<int, X>>));
}
return boost::report_errors();
}

441
test/result_move_assign.cpp Normal file
View File

@ -0,0 +1,441 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <system_error>
#include <iosfwd>
#include <cerrno>
using namespace boost::result;
struct X
{
static int instances;
int v_;
explicit X( int v = 0 ): v_( v ) { ++instances; }
X( X const& r ) = delete;
X( X&& r ): v_( r.v_ ) { r.v_ = 0; ++instances; }
X& operator=( X const& ) = delete;
X& operator=( X&& r )
{
v_ = r.v_;
r.v_ = 0;
return *this;
}
~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;
struct Y
{
static int instances;
int v_;
explicit Y( int v = 0 ): v_( v ) { ++instances; }
Y( Y const& r ) noexcept: v_( r.v_ ) { ++instances; }
Y( Y&& r ) noexcept: v_( r.v_ ) { r.v_ = 0; ++instances; }
Y& operator=( Y const& ) = default;
Y& operator=( Y&& r )
{
v_ = r.v_;
r.v_ = 0;
return *this;
}
~Y() { --instances; }
};
bool operator==( Y const & y1, Y const & y2 )
{
return y1.v_ == y2.v_;
}
std::ostream& operator<<( std::ostream& os, Y const & y )
{
os << "Y:" << y.v_;
return os;
}
int Y::instances = 0;
int main()
{
// default-initialized lhs
{
result<int> r;
result<int> r2;
r2 = std::move( r );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), 0 );
}
{
result<int> r;
result<int> r2( 1 );
r2 = std::move( r );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), 0 );
}
{
result<int> r;
result<int> r2( ENOENT, std::generic_category() );
r2 = std::move( r );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), 0 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r;
result<X> r2;
BOOST_TEST_EQ( X::instances, 2 );
r2 = std::move( r );
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), X() );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r;
result<X> r2( 1 );
BOOST_TEST_EQ( X::instances, 2 );
r2 = std::move( r );
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), X() );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r;
result<X> r2( ENOENT, std::generic_category() );
BOOST_TEST_EQ( X::instances, 1 );
r2 = std::move( r );
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), X() );
}
BOOST_TEST_EQ( X::instances, 0 );
// value lhs
{
result<int> r( 1 );
result<int> r2;
r2 = std::move( r );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), 1 );
BOOST_TEST_EQ( r, r2 );
}
{
result<int> r( 1 );
result<int> r2( 2 );
r2 = std::move( r );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), 1 );
BOOST_TEST_EQ( r, r2 );
}
{
result<int> r( 1 );
result<int> r2( ENOENT, std::generic_category() );
r2 = std::move( r );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), 1 );
BOOST_TEST_EQ( r, r2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1 );
result<X> r2;
BOOST_TEST_EQ( X::instances, 2 );
r2 = std::move( r );
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value().v_, 1 );
BOOST_TEST_EQ( r.value().v_, 0 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1 );
result<X> r2( 2 );
BOOST_TEST_EQ( X::instances, 2 );
r2 = std::move( r );
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value().v_, 1 );
BOOST_TEST_EQ( r.value().v_, 0 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1 );
result<X> r2( ENOENT, std::generic_category() );
BOOST_TEST_EQ( X::instances, 1 );
r2 = std::move( r );
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value().v_, 1 );
BOOST_TEST_EQ( r.value().v_, 0 );
}
BOOST_TEST_EQ( X::instances, 0 );
// error lhs
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
result<int> r2;
r2 = std::move( r );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error(), ec );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
result<int> r2( 1 );
r2 = std::move( r );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error(), ec );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
result<int> r2( ENOENT, std::generic_category() );
r2 = std::move( r );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error(), ec );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<X> r( ec );
result<X> r2;
BOOST_TEST_EQ( X::instances, 1 );
r2 = std::move( r );
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error(), ec );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<X> r( ec );
result<X> r2( 1 );
BOOST_TEST_EQ( X::instances, 1 );
r2 = std::move( r );
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error(), ec );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<X> r( ec );
result<X> r2( ENOENT, std::generic_category() );
BOOST_TEST_EQ( X::instances, 0 );
r2 = std::move( r );
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error(), ec );
}
BOOST_TEST_EQ( X::instances, 0 );
//
BOOST_TEST_EQ( Y::instances, 0 );
{
result<std::string, Y> r( 1 );
result<std::string, Y> r2( 2 );
BOOST_TEST_EQ( Y::instances, 2 );
r2 = std::move( r );
BOOST_TEST_EQ( Y::instances, 2 );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error().v_, 1 );
BOOST_TEST_EQ( r.error().v_, 0 );
}
BOOST_TEST_EQ( Y::instances, 0 );
{
result<std::string, Y> r( 1 );
result<std::string, Y> r2( "str" );
BOOST_TEST_EQ( Y::instances, 1 );
r2 = std::move( r );
BOOST_TEST_EQ( Y::instances, 2 );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error().v_, 1 );
BOOST_TEST_EQ( r.error().v_, 0 );
}
BOOST_TEST_EQ( Y::instances, 0 );
return boost::report_errors();
}

View File

@ -0,0 +1,211 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
using namespace boost::result;
struct X
{
static int instances;
int v_;
X(): v_() { ++instances; }
explicit X( int v ): v_( v ) { ++instances; }
X( int v1, int v2 ): v_( v1+v2 ) { ++instances; }
X( int v1, int v2, int v3 ): v_( v1+v2+v3 ) { ++instances; }
X( X const& r ): v_( r.v_ ) { ++instances; }
X( X&& r ): v_( r.v_ ) { r.v_ = 0; ++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<int> r;
result<int> r2( std::move( r ) );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), 0 );
}
{
result<int> r2( result<int>{} );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), 0 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r;
result<X> r2( std::move( r ) );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), X() );
BOOST_TEST_EQ( X::instances, 2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r2( result<X>{} );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), X() );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<int> r( 1 );
result<int> r2( std::move( r ) );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.value(), 1 );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), 1 );
}
{
result<int> r2( result<int>( 1 ) );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value(), 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1 );
result<X> r2( std::move( r ) );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.value().v_, 0 );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value().v_, 1 );
BOOST_TEST_EQ( X::instances, 2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r2( result<X>( 1 ) );
BOOST_TEST( r2.has_value() );
BOOST_TEST( !r2.has_error() );
BOOST_TEST_EQ( r2.value().v_, 1 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
result<int> r2( std::move( r ) );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error(), ec );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r2( result<int>{ ec } );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error(), ec );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<std::string, X> r( 1 );
result<std::string, X> r2( std::move( r ) );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_EQ( r.error().v_, 0 );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error().v_, 1 );
BOOST_TEST_EQ( X::instances, 2 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<std::string, X> r2( result<std::string, X>( 1 ) );
BOOST_TEST( !r2.has_value() );
BOOST_TEST( r2.has_error() );
BOOST_TEST_EQ( r2.error().v_, 1 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
return boost::report_errors();
}

219
test/result_swap.cpp Normal file
View File

@ -0,0 +1,219 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <system_error>
#include <iosfwd>
#include <cerrno>
using namespace boost::result;
struct X
{
static int instances;
int v_;
explicit X( int v ): v_( v ) { ++instances; }
X( X const& r ) = delete;
X( X&& r ): v_( r.v_ ) { r.v_ = 0; ++instances; }
X& operator=( X const& ) = delete;
X& operator=( X&& r )
{
v_ = r.v_;
r.v_ = 0;
return *this;
}
~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;
struct Y
{
static int instances;
int v_;
explicit Y( int v = 0 ): v_( v ) { ++instances; }
Y( Y const& r ) noexcept: v_( r.v_ ) { ++instances; }
Y( Y&& r ) noexcept: v_( r.v_ ) { r.v_ = 0; ++instances; }
Y& operator=( Y const& ) = default;
Y& operator=( Y&& r )
{
v_ = r.v_;
r.v_ = 0;
return *this;
}
~Y() { --instances; }
};
bool operator==( Y const & y1, Y const & y2 )
{
return y1.v_ == y2.v_;
}
std::ostream& operator<<( std::ostream& os, Y const & y )
{
os << "Y:" << y.v_;
return os;
}
int Y::instances = 0;
int main()
{
{
result<int> r1( 1 ), r1c( r1 );
result<int> r2( 2 ), r2c( r2 );
r1.swap( r2 );
BOOST_TEST_EQ( r1, r2c );
BOOST_TEST_EQ( r2, r1c );
swap( r1, r2 );
BOOST_TEST_EQ( r1, r1c );
BOOST_TEST_EQ( r2, r2c );
}
{
result<int> r1( 1, std::generic_category() ), r1c( r1 );
result<int> r2( 2, std::generic_category() ), r2c( r2 );
r1.swap( r2 );
BOOST_TEST_EQ( r1, r2c );
BOOST_TEST_EQ( r2, r1c );
swap( r1, r2 );
BOOST_TEST_EQ( r1, r1c );
BOOST_TEST_EQ( r2, r2c );
}
{
result<int> r1( 1 ), r1c( r1 );
result<int> r2( 2, std::generic_category() ), r2c( r2 );
r1.swap( r2 );
BOOST_TEST_EQ( r1, r2c );
BOOST_TEST_EQ( r2, r1c );
swap( r1, r2 );
BOOST_TEST_EQ( r1, r1c );
BOOST_TEST_EQ( r2, r2c );
}
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( Y::instances, 0 );
{
result<X, Y> r1( in_place_value, 1 ), r1c( in_place_value, 1 );
result<X, Y> r2( in_place_value, 2 ), r2c( in_place_value, 2 );
BOOST_TEST_EQ( X::instances, 4 );
BOOST_TEST_EQ( Y::instances, 0 );
r1.swap( r2 );
BOOST_TEST_EQ( r1, r2c );
BOOST_TEST_EQ( r2, r1c );
BOOST_TEST_EQ( X::instances, 4 );
BOOST_TEST_EQ( Y::instances, 0 );
swap( r1, r2 );
BOOST_TEST_EQ( r1, r1c );
BOOST_TEST_EQ( r2, r2c );
BOOST_TEST_EQ( X::instances, 4 );
BOOST_TEST_EQ( Y::instances, 0 );
}
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( Y::instances, 0 );
{
result<X, Y> r1( in_place_error, 1 ), r1c( in_place_error, 1 );
result<X, Y> r2( in_place_error, 2 ), r2c( in_place_error, 2 );
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( Y::instances, 4 );
r1.swap( r2 );
BOOST_TEST_EQ( r1, r2c );
BOOST_TEST_EQ( r2, r1c );
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( Y::instances, 4 );
swap( r1, r2 );
BOOST_TEST_EQ( r1, r1c );
BOOST_TEST_EQ( r2, r2c );
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( Y::instances, 4 );
}
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( Y::instances, 0 );
{
result<X, Y> r1( in_place_value, 1 ), r1c( in_place_value, 1 );
result<X, Y> r2( in_place_error, 2 ), r2c( in_place_error, 2 );
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( Y::instances, 2 );
r1.swap( r2 );
BOOST_TEST_EQ( r1, r2c );
BOOST_TEST_EQ( r2, r1c );
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( Y::instances, 2 );
swap( r1, r2 );
BOOST_TEST_EQ( r1, r1c );
BOOST_TEST_EQ( r2, r2c );
BOOST_TEST_EQ( X::instances, 2 );
BOOST_TEST_EQ( Y::instances, 2 );
}
BOOST_TEST_EQ( X::instances, 0 );
BOOST_TEST_EQ( Y::instances, 0 );
return boost::report_errors();
}

View File

@ -0,0 +1,259 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
using namespace boost::result;
struct X
{
int v_;
explicit X( int v ): v_( v ) {}
X( X const& ) = delete;
X& operator=( X const& ) = delete;
};
struct Y
{
};
struct E
{
};
BOOST_NORETURN void throw_exception_from_error_code( Y const & )
{
throw E();
}
int main()
{
{
result<int> r;
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST( r );
BOOST_TEST_NOT( !r );
BOOST_TEST_EQ( r.value(), 0 );
BOOST_TEST_EQ( *r, 0 );
BOOST_TEST_EQ( r.operator->(), &*r );
}
{
result<int> const r;
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST( r );
BOOST_TEST_NOT( !r );
BOOST_TEST_EQ( r.value(), 0 );
BOOST_TEST_EQ( *r, 0 );
BOOST_TEST_EQ( r.operator->(), &*r );
}
{
BOOST_TEST( result<int>().has_value() );
BOOST_TEST( !result<int>().has_error() );
BOOST_TEST( result<int>() );
BOOST_TEST_NOT( !result<int>() );
BOOST_TEST_EQ( result<int>().value(), 0 );
BOOST_TEST_EQ( *result<int>(), 0 );
BOOST_TEST( result<int>().operator->() != 0 );
}
{
result<int> r( 1 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST( r );
BOOST_TEST_NOT( !r );
BOOST_TEST_EQ( r.value(), 1 );
BOOST_TEST_EQ( *r, 1 );
BOOST_TEST_EQ( r.operator->(), &*r );
}
{
result<int> const r( 1 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST( r );
BOOST_TEST_NOT( !r );
BOOST_TEST_EQ( r.value(), 1 );
BOOST_TEST_EQ( *r, 1 );
BOOST_TEST_EQ( r.operator->(), &*r );
}
{
BOOST_TEST( result<int>( 1 ).has_value() );
BOOST_TEST( !result<int>( 1 ).has_error() );
BOOST_TEST( result<int>( 1 ) );
BOOST_TEST_NOT( !result<int>( 1 ) );
BOOST_TEST_EQ( result<int>( 1 ).value(), 1 );
BOOST_TEST_EQ( *result<int>( 1 ), 1 );
BOOST_TEST( result<int>( 1 ).operator->() != 0 );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> r( ec );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_NOT( r );
BOOST_TEST( !r );
BOOST_TEST_THROWS( r.value(), std::system_error );
BOOST_TEST_EQ( r.operator->(), static_cast<int*>(0) );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
result<int> const r( ec );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_NOT( r );
BOOST_TEST( !r );
BOOST_TEST_THROWS( r.value(), std::system_error );
BOOST_TEST_EQ( r.operator->(), static_cast<int*>(0) );
}
{
auto ec = make_error_code( std::errc::invalid_argument );
BOOST_TEST( !result<int>( ec ).has_value() );
BOOST_TEST( result<int>( ec ).has_error() );
BOOST_TEST_NOT( result<int>( ec ) );
BOOST_TEST( !result<int>( ec ) );
BOOST_TEST_THROWS( result<int>( ec ).value(), std::system_error );
BOOST_TEST_EQ( result<int>( ec ).operator->(), static_cast<int*>(0) );
}
{
result<X> r( 1 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST( r );
BOOST_TEST_NOT( !r );
BOOST_TEST_EQ( r.value().v_, 1 );
BOOST_TEST_EQ( (*r).v_, 1 );
BOOST_TEST_EQ( r->v_, 1 );
BOOST_TEST_EQ( r.operator->(), &*r );
}
{
result<X> const r( 1 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST( r );
BOOST_TEST_NOT( !r );
BOOST_TEST_EQ( r.value().v_, 1 );
BOOST_TEST_EQ( (*r).v_, 1 );
BOOST_TEST_EQ( r->v_, 1 );
BOOST_TEST_EQ( r.operator->(), &*r );
}
{
BOOST_TEST( result<X>( 1 ).has_value() );
BOOST_TEST( !result<X>( 1 ).has_error() );
BOOST_TEST( result<X>( 1 ) );
BOOST_TEST_NOT( !result<X>( 1 ) );
BOOST_TEST_EQ( result<X>( 1 ).value().v_, 1 );
BOOST_TEST_EQ( (*result<X>( 1 )).v_, 1 );
BOOST_TEST_EQ( result<X>( 1 )->v_, 1 );
}
{
auto ec = Y();
result<X, Y> r( ec );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_NOT( r );
BOOST_TEST( !r );
BOOST_TEST_THROWS( r.value(), E );
BOOST_TEST_EQ( r.operator->(), static_cast<X*>(0) );
}
{
auto ec = Y();
result<X, Y> const r( ec );
BOOST_TEST( !r.has_value() );
BOOST_TEST( r.has_error() );
BOOST_TEST_NOT( r );
BOOST_TEST( !r );
BOOST_TEST_THROWS( r.value(), E );
BOOST_TEST_EQ( r.operator->(), static_cast<X*>(0) );
}
{
auto ec = Y();
BOOST_TEST(( !result<X, Y>( ec ).has_value() ));
BOOST_TEST(( result<X, Y>( ec ).has_error() ));
BOOST_TEST_NOT(( result<X, Y>( ec ) ));
BOOST_TEST(( !result<X, Y>( ec ) ));
BOOST_TEST_THROWS( (result<X, Y>( ec ).value()), E );
BOOST_TEST_EQ( (result<X, Y>( ec ).operator->()), static_cast<X*>(0) );
}
return boost::report_errors();
}

View File

@ -0,0 +1,125 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/result/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
using namespace boost::result;
struct X
{
static int instances;
int v_;
explicit X( int v ): v_( v ) { ++instances; }
X( int v1, int v2 ): v_( v1+v2 ) { ++instances; }
X( int v1, int v2, int v3 ): v_( v1+v2+v3 ) { ++instances; }
X( X const& ) = delete;
X& operator=( X const& ) = delete;
~X() { --instances; }
};
int X::instances = 0;
int main()
{
{
result<int> r( 0 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.value(), 0 );
}
{
result<int> r = 0;
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.value(), 0 );
}
{
result<int, int> r( in_place_value, 1 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( *r, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.value().v_, 1 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1, 2 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.value().v_, 1+2 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r( 1, 2, 3 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r.value().v_, 1+2+3 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X, X> r( in_place_value, 1 );
BOOST_TEST( r.has_value() );
BOOST_TEST( !r.has_error() );
BOOST_TEST_EQ( r->v_, 1 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
BOOST_TEST_TRAIT_TRUE((std::is_constructible<result<int>, int>));
BOOST_TEST_TRAIT_TRUE((std::is_convertible<int, result<int>>));
BOOST_TEST_TRAIT_FALSE((std::is_constructible<result<int, int>, int>));
BOOST_TEST_TRAIT_FALSE((std::is_constructible<result<int, float>, int>));
BOOST_TEST_TRAIT_TRUE((std::is_constructible<result<X>, int>));
BOOST_TEST_TRAIT_FALSE((std::is_convertible<int, result<X>>));
}
return boost::report_errors();
}