forked from boostorg/system
Add result<U&, E> specialization. Fixes #72.
This commit is contained in:
1 parent
a57c568324
commit
951b3fe7b4
22 files changed
+1808
-4
No files matched your search
@@ -649,6 +649,224 @@ template<class Ch, class Tr, class E> std::basic_ostream<Ch, Tr>& operator<<( st
|
||||
return os;
|
||||
}
|
||||
|
||||
// result<T&, E>
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class U, class A> struct reference_to_temporary: std::integral_constant<bool,
|
||||
!std::is_reference<A>::value ||
|
||||
!std::is_convertible<typename std::remove_reference<A>::type*, U*>::value
|
||||
> {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class U, class E> class result<U&, E>
|
||||
{
|
||||
private:
|
||||
|
||||
variant2::variant<U*, E> v_;
|
||||
|
||||
public:
|
||||
|
||||
using value_type = U&;
|
||||
using error_type = E;
|
||||
|
||||
static constexpr in_place_value_t in_place_value{};
|
||||
static constexpr in_place_error_t in_place_error{};
|
||||
|
||||
public:
|
||||
|
||||
// constructors
|
||||
|
||||
// implicit, value
|
||||
template<class A, typename std::enable_if<
|
||||
std::is_convertible<A, U&>::value &&
|
||||
!detail::reference_to_temporary<U, A>::value &&
|
||||
!std::is_convertible<A, E>::value, int>::type = 0>
|
||||
constexpr result( A&& a )
|
||||
noexcept( std::is_nothrow_constructible<U&, A>::value )
|
||||
: v_( in_place_value, &static_cast<U&>( std::forward<A>(a) ) )
|
||||
{
|
||||
}
|
||||
|
||||
// implicit, error
|
||||
template<class A = E, class = void, typename std::enable_if<
|
||||
std::is_convertible<A, E>::value &&
|
||||
!std::is_convertible<A, U&>::value, int>::type = 0>
|
||||
constexpr result( A&& a )
|
||||
noexcept( std::is_nothrow_constructible<E, A>::value )
|
||||
: v_( in_place_error, std::forward<A>(a) )
|
||||
{
|
||||
}
|
||||
|
||||
// explicit, value
|
||||
template<class A, class En = typename std::enable_if<
|
||||
detail::is_constructible<U&, A>::value &&
|
||||
!std::is_convertible<A, U&>::value &&
|
||||
!detail::reference_to_temporary<U, A>::value &&
|
||||
!detail::is_constructible<E, A>::value
|
||||
>::type>
|
||||
explicit constexpr result( A&& a )
|
||||
noexcept( std::is_nothrow_constructible<U&, A>::value )
|
||||
: v_( in_place_value, &static_cast<U&>( std::forward<A>(a) ) )
|
||||
{
|
||||
}
|
||||
|
||||
// explicit, error
|
||||
template<class... A, class En2 = void, class En = typename std::enable_if<
|
||||
!detail::is_constructible<U&, A...>::value &&
|
||||
detail::is_constructible<E, A...>::value &&
|
||||
sizeof...(A) >= 1
|
||||
>::type>
|
||||
explicit 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<U&, A>::value
|
||||
>::type>
|
||||
constexpr result( in_place_value_t, A&& a )
|
||||
noexcept( std::is_nothrow_constructible<U&, A>::value )
|
||||
: v_( in_place_value, &static_cast<U&>( 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)... )
|
||||
{
|
||||
}
|
||||
|
||||
// converting
|
||||
template<class U2, class E2, class En = typename std::enable_if<
|
||||
std::is_convertible<U2&, U&>::value &&
|
||||
!detail::reference_to_temporary<U, U2&>::value &&
|
||||
std::is_convertible<E2, E>::value &&
|
||||
!std::is_convertible<result<U2&, E2> const&, U&>::value
|
||||
>::type>
|
||||
BOOST_CXX14_CONSTEXPR result( result<U2&, E2> const& r2 )
|
||||
noexcept(
|
||||
std::is_nothrow_constructible<U&, U2&>::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 )
|
||||
{
|
||||
this->emplace( *r2 );
|
||||
}
|
||||
}
|
||||
|
||||
// queries
|
||||
|
||||
constexpr bool has_value() const noexcept
|
||||
{
|
||||
return v_.index() == 0;
|
||||
}
|
||||
|
||||
constexpr bool has_error() const noexcept
|
||||
{
|
||||
return v_.index() == 1;
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const noexcept
|
||||
{
|
||||
return v_.index() == 0;
|
||||
}
|
||||
|
||||
// checked value access
|
||||
|
||||
BOOST_CXX14_CONSTEXPR U& value( boost::source_location const& loc = BOOST_CURRENT_LOCATION ) const
|
||||
{
|
||||
if( has_value() )
|
||||
{
|
||||
return *variant2::unsafe_get<0>( v_ );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw_exception_from_error( variant2::unsafe_get<1>( v_ ), loc );
|
||||
}
|
||||
}
|
||||
|
||||
// unchecked value access
|
||||
|
||||
BOOST_CXX14_CONSTEXPR U* operator->() const noexcept
|
||||
{
|
||||
return has_value()? variant2::unsafe_get<0>( v_ ): 0;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR U& operator*() const noexcept
|
||||
{
|
||||
U* p = operator->();
|
||||
|
||||
BOOST_ASSERT( p != 0 );
|
||||
|
||||
return *p;
|
||||
}
|
||||
|
||||
// error access
|
||||
|
||||
constexpr E error() const &
|
||||
noexcept( std::is_nothrow_default_constructible<E>::value && std::is_nothrow_copy_constructible<E>::value )
|
||||
{
|
||||
return has_error()? variant2::unsafe_get<1>( v_ ): E();
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR E error() &&
|
||||
noexcept( std::is_nothrow_default_constructible<E>::value && std::is_nothrow_move_constructible<E>::value )
|
||||
{
|
||||
return has_error()? std::move( variant2::unsafe_get<1>( v_ ) ): E();
|
||||
}
|
||||
|
||||
// emplace
|
||||
|
||||
template<class A, class En = typename std::enable_if<
|
||||
detail::is_constructible<U&, A>::value &&
|
||||
!detail::reference_to_temporary<U, A>::value
|
||||
>::type>
|
||||
BOOST_CXX14_CONSTEXPR U& emplace( A&& a )
|
||||
{
|
||||
return *v_.template emplace<0>( &static_cast<U&>( a ) );
|
||||
}
|
||||
|
||||
// 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 && r2? *r1 == *r2: r1.v_ == r2.v_ ) )
|
||||
{
|
||||
return r1 && r2? *r1 == *r2: r1.v_ == r2.v_;
|
||||
}
|
||||
|
||||
friend constexpr bool operator!=( result const & r1, result const & r2 )
|
||||
noexcept( noexcept( !( r1 == r2 ) ) )
|
||||
{
|
||||
return !( r1 == r2 );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace system
|
||||
} // namespace boost
|
||||
|
||||
|
||||
Reference in new issue
Block a user