mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-17 08:37:17 -04:00
Support for expected<void, E>
This commit is contained in:
parent
b1adc8704b
commit
aa5ee5775a
@ -58,6 +58,24 @@ union trivial_expected_storage {
|
|||||||
~trivial_expected_storage() = default;
|
~trivial_expected_storage() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
union trivial_expected_storage <void, E> {
|
||||||
|
typedef void value_type;
|
||||||
|
typedef E error_type;
|
||||||
|
|
||||||
|
error_type error;
|
||||||
|
|
||||||
|
constexpr trivial_expected_storage() {
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr trivial_expected_storage(const exceptional<error_type>& e) : error(e.error){
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
~trivial_expected_storage() = default;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T, typename E>
|
template<typename T, typename E>
|
||||||
union non_trivial_expected_storage {
|
union non_trivial_expected_storage {
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
@ -82,6 +100,24 @@ union non_trivial_expected_storage {
|
|||||||
~non_trivial_expected_storage() {};
|
~non_trivial_expected_storage() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
union non_trivial_expected_storage <void, E> {
|
||||||
|
typedef void value_type;
|
||||||
|
typedef E error_type;
|
||||||
|
|
||||||
|
error_type error;
|
||||||
|
|
||||||
|
constexpr non_trivial_expected_storage(){
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr non_trivial_expected_storage(exceptional<error_type>& e) : error(e.error){
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
~non_trivial_expected_storage() {};
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T, typename E>
|
template<typename T, typename E>
|
||||||
struct trivial_expected_base {
|
struct trivial_expected_base {
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
@ -113,6 +149,28 @@ struct trivial_expected_base {
|
|||||||
~trivial_expected_base() = default;
|
~trivial_expected_base() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
struct trivial_expected_base <void, E> {
|
||||||
|
typedef E error_type;
|
||||||
|
|
||||||
|
bool has_value;
|
||||||
|
trivial_expected_storage<void, E> storage;
|
||||||
|
|
||||||
|
trivial_expected_base() : has_value(true), storage(){
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
trivial_expected_base(only_set_valid_t, bool hv) : has_value(hv){
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
trivial_expected_base(const exceptional<error_type>& e) : has_value(false), storage(e) {
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
~trivial_expected_base() = default;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T, typename E>
|
template<typename T, typename E>
|
||||||
struct non_trivial_expected_base {
|
struct non_trivial_expected_base {
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
@ -150,6 +208,32 @@ struct non_trivial_expected_base {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
struct non_trivial_expected_base <void, E> {
|
||||||
|
typedef E error_type;
|
||||||
|
|
||||||
|
bool has_value;
|
||||||
|
trivial_expected_storage<void, E> storage;
|
||||||
|
|
||||||
|
non_trivial_expected_base() : has_value(true), storage(){
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
non_trivial_expected_base(only_set_valid_t, bool hv) : has_value(hv){
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
non_trivial_expected_base(const exceptional<error_type>& e) : has_value(false), storage(e) {
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
~non_trivial_expected_base(){
|
||||||
|
if(!has_value){
|
||||||
|
storage.error.~error_type();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, typename E>
|
template <typename T, typename E>
|
||||||
using expected_base = typename std::conditional<
|
using expected_base = typename std::conditional<
|
||||||
std::is_trivially_destructible<T>::value && std::is_trivially_destructible<E>::value,
|
std::is_trivially_destructible<T>::value && std::is_trivially_destructible<E>::value,
|
||||||
@ -338,6 +422,119 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
struct expected <void, E> : expected_base<void, E> {
|
||||||
|
typedef void value_type;
|
||||||
|
typedef E error_type;
|
||||||
|
|
||||||
|
typedef expected<void, E> this_type;
|
||||||
|
typedef expected_base<void, E> base_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
error_type* error_ptr() {
|
||||||
|
return std::addressof(base_type::storage.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const error_type* error_ptr() const {
|
||||||
|
return static_addressof(base_type::storage.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const bool& contained_has_value() const& {
|
||||||
|
return base_type::has_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool& contained_has_value() & {
|
||||||
|
return base_type::has_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool&& contained_has_value() && {
|
||||||
|
return std::move(base_type::has_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const error_type& contained_error() const& {
|
||||||
|
return base_type::storage.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_type& contained_error() & {
|
||||||
|
return base_type::storage.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_type&& contained_error() && {
|
||||||
|
return std::move(base_type::storage.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Constructors */
|
||||||
|
|
||||||
|
expected(const expected& rhs) : base_type(only_set_valid, rhs.valid()) {
|
||||||
|
if(!rhs.valid()){
|
||||||
|
::new (error_ptr()) error_type(rhs.contained_error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expected(expected&& rhs) : base_type(only_set_valid, rhs.valid()) {
|
||||||
|
if(!rhs.valid()){
|
||||||
|
new (error_ptr()) error_type(std::move(rhs.contained_error()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expected(const exceptional<error_type>& e) : base_type(e) {
|
||||||
|
//Nothing else to init
|
||||||
|
}
|
||||||
|
|
||||||
|
expected() : base_type() {}
|
||||||
|
|
||||||
|
~expected() = default;
|
||||||
|
|
||||||
|
/* Operators */
|
||||||
|
expected& operator=(const expected& rhs){
|
||||||
|
this_type(rhs).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
expected& operator=(expected&& rhs){
|
||||||
|
this_type(std::move(rhs)).swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Swap */
|
||||||
|
|
||||||
|
void swap(expected& rhs){
|
||||||
|
if (valid()){
|
||||||
|
if (!rhs.valid()){
|
||||||
|
error_type t = std::move(rhs.contained_error());
|
||||||
|
new (error_ptr()) error_type(t);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!rhs.valid()){
|
||||||
|
std::swap(contained_error(), rhs.contained_error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Accessors */
|
||||||
|
|
||||||
|
constexpr bool valid() const {
|
||||||
|
return contained_has_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr explicit operator bool() const {
|
||||||
|
return valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const error_type& error() const {
|
||||||
|
return contained_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool has_error(const error_type& e) const {
|
||||||
|
return contained_error() == e;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr exceptional<error_type> get_exceptional() const {
|
||||||
|
return exceptional<error_type>(contained_error());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline expected<T> make_expected(T&& v){
|
inline expected<T> make_expected(T&& v){
|
||||||
return expected<T>(std::forward<T>(v));
|
return expected<T>(std::forward<T>(v));
|
||||||
@ -358,6 +555,10 @@ inline expected<T, E> make_expected_from_error(E v){
|
|||||||
return expected<T, E>(exceptional<E>(v));
|
return expected<T, E>(exceptional<E>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline expected<void> make_expected(){
|
||||||
|
return expected<void>();
|
||||||
|
}
|
||||||
|
|
||||||
} //end of namespace std
|
} //end of namespace std
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user