Compare commits

...

12 Commits

9 changed files with 363 additions and 29 deletions

View File

@ -47,6 +47,10 @@ jobs:
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: g++-11
- toolset: gcc-12
cxxstd: "03,11,14,17,20"
os: ubuntu-22.04
install: g++-12
- toolset: clang
compiler: clang++-3.9
cxxstd: "03,11,14"
@ -92,11 +96,21 @@ jobs:
os: ubuntu-20.04
- toolset: clang
compiler: clang++-12
cxxstd: "03,11,14,17,2a"
cxxstd: "03,11,14,17,20"
os: ubuntu-20.04
- toolset: clang
compiler: clang++-13
cxxstd: "03,11,14,17,20"
os: ubuntu-22.04
install: clang-13
- toolset: clang
compiler: clang++-14
cxxstd: "03,11,14,17,20"
os: ubuntu-22.04
install: clang-14
- toolset: clang
cxxstd: "03,11,14,17,2a"
os: macos-10.15
os: macos-11
runs-on: ${{matrix.os}}
@ -205,7 +219,8 @@ jobs:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
- os: macos-10.15
- os: ubuntu-22.04
- os: macos-11
runs-on: ${{matrix.os}}
@ -251,7 +266,8 @@ jobs:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
- os: macos-10.15
- os: ubuntu-22.04
- os: macos-11
runs-on: ${{matrix.os}}
@ -307,7 +323,8 @@ jobs:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
- os: macos-10.15
- os: ubuntu-22.04
- os: macos-11
runs-on: ${{matrix.os}}

25
README.md Normal file
View File

@ -0,0 +1,25 @@
# Boost.System
The Boost.System library, part of [Boost C++ Libraries](https://boost.org),
implements an extensible framework for error reporting in the form of an
`error_code` class and supporting facilities.
It has been proposed for the C++11 standard, has been accepted, and
is now available as part of the standard library in the `<system_error>`
header. However, the Boost implementation has continued to evolve and
gain enhancements and additional functionality, such as support for
attaching [source locations](https://www.boost.org/doc/libs/release/libs/assert/doc/html/assert.html#source_location_support)
to `error_code`, and a `result<T>` class that can carry either a value
or an error code.
See [the documentation of System](http://boost.org/libs/system) for more
information.
Since `<system_error>` is a relatively undocumented portion of the C++
standard library, the documentation of Boost.System may be useful to you
even if you use the standard components.
## License
Distributed under the
[Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).

View File

@ -14,6 +14,9 @@ https://www.boost.org/LICENSE_1_0.txt
to `error_code`, the original is now restored, if possible.
* Reworked the conversion from `error_category` to `std::error_category`
to avoid the one-time allocation that shows up on leak checkers.
* Added a constructor that allows replacing the source location of an
`error_code`, and a corresponding `assign`.
* Added a converting constructor to `result`.
## Changes in Boost 1.79

View File

@ -610,9 +610,8 @@ public:
template<class ErrorCodeEnum>
constexpr error_code( ErrorCodeEnum e ) noexcept;
template<class ErrorCodeEnum>
error_code( ErrorCodeEnum e, boost::source_location const * loc )
noexcept;
error_code( error_code const& ec,
boost::source_location const * loc ) noexcept;
error_code( std::error_code const& ec ) noexcept;
@ -626,9 +625,8 @@ public:
template<class ErrorCodeEnum>
constexpr error_code & operator=( ErrorCodeEnum e ) noexcept;
template<class ErrorCodeEnum>
void assign( ErrorCodeEnum e,
boost::source_location const * loc ) noexcept;
void assign( error_code const& ec,
boost::source_location const * loc ) noexcept;
constexpr void clear() noexcept;
@ -757,17 +755,17 @@ Ensures: :: `*this == make_error_code( e )`.
Remarks: :: This constructor is only enabled when `is_error_code_enum<ErrorCodeEnum>::value` is `true`.
```
template<class ErrorCodeEnum>
error_code( ErrorCodeEnum e, boost::source_location const * loc ) noexcept;
error_code( error_code const& ec,
boost::source_location const * loc ) noexcept;
```
[none]
* {blank}
+
Requires: :: `loc` points to a valid `boost::source_location` object with static storage duration.
Ensures: :: `*this == make_error_code( e )`.
Remarks: :: This constructor is only enabled when `is_error_code_enum<ErrorCodeEnum>::value` is `true`.
When `make_error_code( e )` is not a default-constructed `error_code` and doesn't wrap a
`std::error_code`, `has_location()` is `true` and `&location()` is `loc`.
Requires: :: `loc` points to a valid `boost::source_location` object with static storage duration, or is `nullptr`.
Ensures: :: `*this == ec`.
Remarks: :: When `ec` is a default-constructed `error_code` or wraps a `std::error_code`,
or when `loc` is `nullptr`, `*this` stores no location (`has_location()` is `false`).
Otherwise, `*this` stores `loc` (`has_location()` is `true` and `&location()` is `loc`.)
```
error_code( std::error_code const & ec ) noexcept;
@ -808,16 +806,13 @@ Ensures: :: `*this == make_error_code( e )`.
Remarks: :: This operator is only enabled when `is_error_code_enum<ErrorCodeEnum>::value` is `true`.
```
template<class ErrorCodeEnum>
void assign( ErrorCodeEnum e,
boost::source_location const * loc ) noexcept;
void assign( error_code const& ec,
boost::source_location const * loc ) noexcept;
```
[none]
* {blank}
+
Requires: :: `loc` points to a valid `boost::source_location` object with static storage duration.
Effects: :: `*this = error_code( e, loc )`.
Remarks: :: This function is only enabled when `is_error_code_enum<ErrorCodeEnum>::value` is `true`.
Effects: :: `*this = error_code( ec, loc )`.
```
constexpr void clear() noexcept;
@ -1613,6 +1608,12 @@ public:
template<class... A>
constexpr result( in_place_error_t, A&&... a );
template<class T2, class E2>
constexpr result( result<T2, E2> const& r2 );
template<class T2, class E2>
constexpr result( result<T2, E2>&& r2 );
// queries
constexpr bool has_value() const noexcept;
@ -1721,6 +1722,30 @@ Ensures: ::
Remarks: ::
This constructor is only enabled when `std::is_constructible<E, A...>::value` is `true`.
```
template<class T2, class E2>
constexpr result( result<T2, E2> const& r2 );
```
[none]
* {blank}
+
Ensures: ::
If `r2.has_value()` is `true`, `*this` holds the value `T( *r2 )`, otherwise `*this` holds the value `E( r2.error() )`.
Remarks: ::
This constructor is only enabled when `std::is_convertible<T2, T>::value && std::is_convertible<E2, E>::value` is `true`.
```
template<class T2, class E2>
constexpr result( result<T2, E2>&& r2 );
```
[none]
* {blank}
+
Ensures: ::
If `r2.has_value()` is `true`, `*this` holds the value `T( std::move( *r2 ) )`, otherwise `*this` holds the value `E( r2.error() )`.
Remarks: ::
This constructor is only enabled when `std::is_convertible<T2, T>::value && std::is_convertible<E2, E>::value` is `true`.
#### Queries
```

View File

@ -135,7 +135,8 @@ public:
template<class... A, class En = typename std::enable_if<
std::is_constructible<T, A...>::value &&
!(detail::is_errc_t<A...>::value && std::is_arithmetic<T>::value) &&
!std::is_constructible<E, A...>::value
!std::is_constructible<E, A...>::value &&
sizeof...(A) >= 1
>::type>
explicit constexpr result( A&&... a )
noexcept( std::is_nothrow_constructible<T, A...>::value )
@ -146,7 +147,8 @@ public:
// explicit, 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
std::is_constructible<E, A...>::value &&
sizeof...(A) >= 1
>::type>
explicit constexpr result( A&&... a )
noexcept( std::is_nothrow_constructible<E, A...>::value )
@ -174,6 +176,43 @@ public:
{
}
// converting
template<class T2, class E2, class En = typename std::enable_if<
std::is_convertible<T2, T>::value &&
std::is_convertible<E2, E>::value
>::type>
BOOST_CXX14_CONSTEXPR result( result<T2, E2> const& r2 )
noexcept(
std::is_nothrow_constructible<T, T2 const&>::value &&
std::is_nothrow_constructible<E, E2>::value &&
std::is_nothrow_default_constructible<E2>::value &&
std::is_nothrow_copy_constructible<E2>::value )
: v_( in_place_error, r2.error() )
{
if( r2 )
{
v_.template emplace<0>( *r2 );
}
}
template<class T2, class E2, class En = typename std::enable_if<
std::is_convertible<T2, T>::value &&
std::is_convertible<E2, E>::value
>::type>
BOOST_CXX14_CONSTEXPR result( result<T2, E2>&& r2 )
noexcept(
std::is_nothrow_constructible<T, T2&&>::value &&
std::is_nothrow_constructible<E, E2>::value &&
std::is_nothrow_default_constructible<E2>::value &&
std::is_nothrow_copy_constructible<E2>::value )
: v_( in_place_error, r2.error() )
{
if( r2 )
{
v_.template emplace<0>( std::move( *r2 ) );
}
}
// queries
constexpr bool has_value() const noexcept
@ -183,7 +222,7 @@ public:
constexpr bool has_error() const noexcept
{
return v_.index() != 0;
return v_.index() == 1;
}
constexpr explicit operator bool() const noexcept
@ -472,7 +511,7 @@ public:
constexpr bool has_error() const noexcept
{
return v_.index() != 0;
return v_.index() == 1;
}
constexpr explicit operator bool() const noexcept

View File

@ -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)

View File

@ -61,7 +61,11 @@ run single_instance_test.cpp single_instance_lib1 single_instance_lib2 : : : <li
run single_instance_test.cpp single_instance_lib1 single_instance_lib2 : : : <link>shared : single_instance_lib_shared ;
system-run before_main_test.cpp ;
run-fail throws_assign_fail.cpp ;
run-fail throws_assign_fail.cpp : : :
# GCC 12 catches this at compile time with a warning
<toolset>gcc,<variant>release:<build>no ;
system-run constexpr_test.cpp ;
system-run win32_hresult_test.cpp ;
@ -169,3 +173,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) ;

View File

@ -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 <boost/system/result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
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<int> r( 5 );
result<long> r2 = r;
BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 5 );
}
{
result<int> const r( 6 );
result<long> r2 = r;
BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 6 );
}
{
result<long> r2 = result<int>( 7 );
BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 7 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<int> r( 5 );
result<X> r2 = r;
BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 5 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<int> const r( 6 );
result<X> r2 = r;
BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, 6 );
BOOST_TEST_EQ( X::instances, 1 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<X> r2 = result<int>( 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<int> r( ec );
result<long> r2 = r;
BOOST_TEST( !r2 );
BOOST_TEST_EQ( r2.error(), ec );
}
{
auto ec = make_error_code( errc::invalid_argument );
result<int> r( ec );
result<long> r2 = r;
BOOST_TEST( !r2 );
BOOST_TEST_EQ( r2.error(), ec );
}
{
auto ec = make_error_code( errc::invalid_argument );
result<long> r2 = result<int>( ec );
BOOST_TEST( !r2 );
BOOST_TEST_EQ( r2.error(), ec );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<char const*, int> r( "test" );
result<std::string, X> 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<char const*, int> const r( "test" );
result<std::string, X> 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<std::string, X> r2 = result<char const*, int>( "test" );
BOOST_TEST( r2 ) && BOOST_TEST_EQ( *r2, std::string( "test" ) );
BOOST_TEST_EQ( X::instances, 0 );
}
BOOST_TEST_EQ( X::instances, 0 );
{
result<char const*, int> r( 5 );
result<std::string, X> 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<char const*, int> const r( 6 );
result<std::string, X> r2 = r;
BOOST_TEST( !r2 );
BOOST_TEST_EQ( r2.error(), X(6) );
BOOST_TEST_EQ( X::instances, 1 );
}
{
result<std::string, X> r2 = result<char const*, int>( 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<long>, result<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_convertible<result<int>, result<long>>));
BOOST_TEST_TRAIT_FALSE((std::is_constructible<result<int>, result<void*>>));
BOOST_TEST_TRAIT_FALSE((std::is_convertible<result<void*>, result<int>>));
BOOST_TEST_TRAIT_FALSE((std::is_constructible<result<int>, result<void>>));
BOOST_TEST_TRAIT_FALSE((std::is_convertible<result<void>, result<int>>));
BOOST_TEST_TRAIT_FALSE((std::is_constructible<result<void>, result<int>>));
BOOST_TEST_TRAIT_FALSE((std::is_convertible<result<int>, result<void>>));
BOOST_TEST_TRAIT_FALSE((std::is_constructible<result<int, void*>, result<int, int>>));
BOOST_TEST_TRAIT_FALSE((std::is_convertible<result<int, int>, result<int, void*>>));
}
return boost::report_errors();
}

View File

@ -12,6 +12,11 @@ struct X
{
};
struct Y
{
Y( int );
};
int main()
{
{
@ -37,5 +42,17 @@ int main()
BOOST_TEST( !r.has_error() );
}
{
BOOST_TEST_TRAIT_TRUE((std::is_default_constructible<result<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_default_constructible<result<int, int>>));
BOOST_TEST_TRAIT_TRUE((std::is_default_constructible<result<X>>));
BOOST_TEST_TRAIT_TRUE((std::is_default_constructible<result<X, int>>));
BOOST_TEST_TRAIT_TRUE((std::is_default_constructible<result<void>>));
BOOST_TEST_TRAIT_TRUE((std::is_default_constructible<result<void, int>>));
BOOST_TEST_TRAIT_FALSE((std::is_default_constructible<result<Y>>));
BOOST_TEST_TRAIT_FALSE((std::is_default_constructible<result<Y, int>>));
}
return boost::report_errors();
}