feat():initial version
This commit is contained in:
480
install/boost_1_75_0/include/boost/leaf/result.hpp
Normal file
480
install/boost_1_75_0/include/boost/leaf/result.hpp
Normal file
@@ -0,0 +1,480 @@
|
||||
#ifndef BOOST_LEAF_RESULT_HPP_INCLUDED
|
||||
#define BOOST_LEAF_RESULT_HPP_INCLUDED
|
||||
|
||||
// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_LEAF_ENABLE_WARNINGS
|
||||
# if defined(__clang__)
|
||||
# pragma clang system_header
|
||||
# elif (__GNUC__*100+__GNUC_MINOR__>301)
|
||||
# pragma GCC system_header
|
||||
# elif defined(_MSC_VER)
|
||||
# pragma warning(push,1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/leaf/error.hpp>
|
||||
#include <climits>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
class bad_result:
|
||||
public std::exception,
|
||||
public error_id
|
||||
{
|
||||
char const * what() const noexcept final override
|
||||
{
|
||||
return "boost::leaf::bad_result";
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit bad_result( error_id id ) noexcept:
|
||||
error_id(id)
|
||||
{
|
||||
BOOST_LEAF_ASSERT(value());
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class T>
|
||||
struct stored
|
||||
{
|
||||
using type = T;
|
||||
using value_type = T;
|
||||
using value_type_const = T const;
|
||||
using value_cref = T const &;
|
||||
using value_ref = T &;
|
||||
using value_rv_cref = T const &&;
|
||||
using value_rv_ref = T &&;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct stored<T &>
|
||||
{
|
||||
using type = std::reference_wrapper<T>;
|
||||
using value_type_const = T;
|
||||
using value_type = T;
|
||||
using value_ref = T &;
|
||||
using value_cref = T &;
|
||||
using value_rv_ref = T &;
|
||||
using value_rv_cref = T &;
|
||||
};
|
||||
|
||||
class result_discriminant
|
||||
{
|
||||
unsigned state_;
|
||||
|
||||
public:
|
||||
|
||||
enum kind_t
|
||||
{
|
||||
no_error = 0,
|
||||
err_id = 1,
|
||||
ctx_ptr = 2,
|
||||
val = 3
|
||||
};
|
||||
|
||||
explicit result_discriminant( error_id id ) noexcept:
|
||||
state_(id.value())
|
||||
{
|
||||
BOOST_LEAF_ASSERT(state_==0 || (state_&3)==1);
|
||||
}
|
||||
|
||||
struct kind_val { };
|
||||
explicit result_discriminant( kind_val ) noexcept:
|
||||
state_(val)
|
||||
{
|
||||
}
|
||||
|
||||
struct kind_ctx_ptr { };
|
||||
explicit result_discriminant( kind_ctx_ptr ) noexcept:
|
||||
state_(ctx_ptr)
|
||||
{
|
||||
}
|
||||
|
||||
kind_t kind() const noexcept
|
||||
{
|
||||
return kind_t(state_&3);
|
||||
}
|
||||
|
||||
error_id get_error_id() const noexcept
|
||||
{
|
||||
BOOST_LEAF_ASSERT(kind()==no_error || kind()==err_id);
|
||||
return make_error_id(state_);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class result
|
||||
{
|
||||
template <class U>
|
||||
friend class result;
|
||||
|
||||
using result_discriminant = leaf_detail::result_discriminant;
|
||||
|
||||
struct error_result
|
||||
{
|
||||
error_result( error_result && ) = default;
|
||||
error_result( error_result const & ) = delete;
|
||||
error_result & operator=( error_result const & ) = delete;
|
||||
|
||||
result & r_;
|
||||
|
||||
error_result( result & r ) noexcept:
|
||||
r_(r)
|
||||
{
|
||||
}
|
||||
|
||||
template <class U>
|
||||
operator result<U>() noexcept
|
||||
{
|
||||
switch(r_.what_.kind())
|
||||
{
|
||||
case result_discriminant::val:
|
||||
return result<U>(error_id());
|
||||
case result_discriminant::ctx_ptr:
|
||||
return result<U>(std::move(r_.ctx_));
|
||||
default:
|
||||
return result<U>(std::move(r_.what_));
|
||||
}
|
||||
}
|
||||
|
||||
operator error_id() noexcept
|
||||
{
|
||||
switch(r_.what_.kind())
|
||||
{
|
||||
case result_discriminant::val:
|
||||
return error_id();
|
||||
case result_discriminant::ctx_ptr:
|
||||
{
|
||||
error_id captured_id = r_.ctx_->propagate_captured_errors();
|
||||
leaf_detail::id_factory<>::current_id = captured_id.value();
|
||||
return captured_id;
|
||||
}
|
||||
default:
|
||||
return r_.what_.get_error_id();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using stored_type = typename leaf_detail::stored<T>::type;
|
||||
using value_type = typename leaf_detail::stored<T>::value_type;
|
||||
using value_type_const = typename leaf_detail::stored<T>::value_type_const;
|
||||
using value_ref = typename leaf_detail::stored<T>::value_ref;
|
||||
using value_cref = typename leaf_detail::stored<T>::value_cref;
|
||||
using value_rv_ref = typename leaf_detail::stored<T>::value_rv_ref;
|
||||
using value_rv_cref = typename leaf_detail::stored<T>::value_rv_cref;
|
||||
|
||||
union
|
||||
{
|
||||
stored_type stored_;
|
||||
context_ptr ctx_;
|
||||
};
|
||||
|
||||
result_discriminant what_;
|
||||
|
||||
void destroy() const noexcept
|
||||
{
|
||||
switch(this->what_.kind())
|
||||
{
|
||||
case result_discriminant::val:
|
||||
stored_.~stored_type();
|
||||
break;
|
||||
case result_discriminant::ctx_ptr:
|
||||
BOOST_LEAF_ASSERT(!ctx_ || ctx_->captured_id_);
|
||||
ctx_.~context_ptr();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <class U>
|
||||
result_discriminant move_from( result<U> && x ) noexcept
|
||||
{
|
||||
auto x_what = x.what_;
|
||||
switch(x_what.kind())
|
||||
{
|
||||
case result_discriminant::val:
|
||||
(void) new(&stored_) stored_type(std::move(x.stored_));
|
||||
break;
|
||||
case result_discriminant::ctx_ptr:
|
||||
BOOST_LEAF_ASSERT(!x.ctx_ || x.ctx_->captured_id_);
|
||||
(void) new(&ctx_) context_ptr(std::move(x.ctx_));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return x_what;
|
||||
}
|
||||
|
||||
result( result_discriminant && what ) noexcept:
|
||||
what_(std::move(what))
|
||||
{
|
||||
BOOST_LEAF_ASSERT(what_.kind()==result_discriminant::err_id || what_.kind()==result_discriminant::no_error);
|
||||
}
|
||||
|
||||
error_id get_error_id() const noexcept
|
||||
{
|
||||
BOOST_LEAF_ASSERT(what_.kind()!=result_discriminant::val);
|
||||
return what_.kind()==result_discriminant::ctx_ptr ? ctx_->captured_id_ : what_.get_error_id();
|
||||
}
|
||||
|
||||
static int init_T_with_U( T && );
|
||||
|
||||
protected:
|
||||
|
||||
void enforce_value_state() const
|
||||
{
|
||||
if( what_.kind() != result_discriminant::val )
|
||||
::boost::leaf::throw_exception(bad_result(get_error_id()));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
result( result && x ) noexcept:
|
||||
what_(move_from(std::move(x)))
|
||||
{
|
||||
}
|
||||
|
||||
template <class U>
|
||||
result( result<U> && x ) noexcept:
|
||||
what_(move_from(std::move(x)))
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
result():
|
||||
stored_(stored_type()),
|
||||
what_(result_discriminant::kind_val{})
|
||||
{
|
||||
}
|
||||
|
||||
result( value_type && v ) noexcept:
|
||||
stored_(std::forward<value_type>(v)),
|
||||
what_(result_discriminant::kind_val{})
|
||||
{
|
||||
}
|
||||
|
||||
result( value_type const & v ):
|
||||
stored_(v),
|
||||
what_(result_discriminant::kind_val{})
|
||||
{
|
||||
}
|
||||
|
||||
result( error_id err ) noexcept:
|
||||
what_(err)
|
||||
{
|
||||
}
|
||||
|
||||
// SFINAE: T can be initialized with a U, e.g. result<std::string>("literal").
|
||||
// Not using is_constructible on purpose, bug with COMPILER=/usr/bin/clang++ CXXSTD=11 clang 3.3.
|
||||
template <class U>
|
||||
result( U && u, decltype(init_T_with_U(std::forward<U>(u))) * = 0 ):
|
||||
stored_(std::forward<U>(u)),
|
||||
what_(result_discriminant::kind_val{})
|
||||
{
|
||||
}
|
||||
|
||||
result( std::error_code const & ec ) noexcept:
|
||||
what_(error_id(ec))
|
||||
{
|
||||
}
|
||||
|
||||
template <class Enum>
|
||||
result( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, int>::type * = 0 ) noexcept:
|
||||
what_(error_id(e))
|
||||
{
|
||||
}
|
||||
|
||||
result( context_ptr && ctx ) noexcept:
|
||||
ctx_(std::move(ctx)),
|
||||
what_(result_discriminant::kind_ctx_ptr{})
|
||||
{
|
||||
}
|
||||
|
||||
~result() noexcept
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
result & operator=( result && x ) noexcept
|
||||
{
|
||||
destroy();
|
||||
what_ = move_from(std::move(x));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
result & operator=( result<U> && x ) noexcept
|
||||
{
|
||||
destroy();
|
||||
what_ = move_from(std::move(x));
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return what_.kind() == result_discriminant::val;
|
||||
}
|
||||
|
||||
value_cref value() const &
|
||||
{
|
||||
enforce_value_state();
|
||||
return stored_;
|
||||
}
|
||||
|
||||
value_ref value() &
|
||||
{
|
||||
enforce_value_state();
|
||||
return stored_;
|
||||
}
|
||||
|
||||
value_rv_cref value() const &&
|
||||
{
|
||||
enforce_value_state();
|
||||
return std::move(stored_);
|
||||
}
|
||||
|
||||
value_rv_ref value() &&
|
||||
{
|
||||
enforce_value_state();
|
||||
return std::move(stored_);
|
||||
}
|
||||
|
||||
value_cref operator*() const &
|
||||
{
|
||||
return value();
|
||||
}
|
||||
|
||||
value_ref operator*() &
|
||||
{
|
||||
return value();
|
||||
}
|
||||
|
||||
value_rv_cref operator*() const &&
|
||||
{
|
||||
return value();
|
||||
}
|
||||
|
||||
value_rv_ref operator*() &&
|
||||
{
|
||||
return value();
|
||||
}
|
||||
|
||||
value_type_const * operator->() const
|
||||
{
|
||||
return &value();
|
||||
}
|
||||
|
||||
value_type * operator->()
|
||||
{
|
||||
return &value();
|
||||
}
|
||||
|
||||
error_result error() noexcept
|
||||
{
|
||||
return error_result{*this};
|
||||
}
|
||||
|
||||
template <class... Item>
|
||||
error_id load( Item && ... item ) noexcept
|
||||
{
|
||||
return error_id(error()).load(std::forward<Item>(item)...);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
struct void_ { };
|
||||
}
|
||||
|
||||
template <>
|
||||
class result<void>:
|
||||
result<leaf_detail::void_>
|
||||
{
|
||||
using result_discriminant = leaf_detail::result_discriminant;
|
||||
using void_ = leaf_detail::void_;
|
||||
using base = result<void_>;
|
||||
|
||||
template <class U>
|
||||
friend class result;
|
||||
|
||||
result( result_discriminant && what ) noexcept:
|
||||
base(std::move(what))
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
using value_type = void;
|
||||
|
||||
result( result && x ) noexcept:
|
||||
base(std::move(x))
|
||||
{
|
||||
}
|
||||
|
||||
result() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
result( error_id err ) noexcept:
|
||||
base(err)
|
||||
{
|
||||
}
|
||||
|
||||
result( std::error_code const & ec ) noexcept:
|
||||
base(ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Enum>
|
||||
result( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, Enum>::type * = 0 ) noexcept:
|
||||
base(e)
|
||||
{
|
||||
}
|
||||
|
||||
result( context_ptr && ctx ) noexcept:
|
||||
base(std::move(ctx))
|
||||
{
|
||||
}
|
||||
|
||||
~result() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void value() const
|
||||
{
|
||||
base::enforce_value_state();
|
||||
}
|
||||
|
||||
using base::operator=;
|
||||
using base::operator bool;
|
||||
using base::get_error_id;
|
||||
using base::error;
|
||||
using base::load;
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class R>
|
||||
struct is_result_type;
|
||||
|
||||
template <class T>
|
||||
struct is_result_type<result<T>>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user