mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-15 15:37:51 -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;
|
||||
};
|
||||
|
||||
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>
|
||||
union non_trivial_expected_storage {
|
||||
typedef T value_type;
|
||||
@ -82,6 +100,24 @@ union 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>
|
||||
struct trivial_expected_base {
|
||||
typedef T value_type;
|
||||
@ -113,6 +149,28 @@ struct trivial_expected_base {
|
||||
~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>
|
||||
struct non_trivial_expected_base {
|
||||
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>
|
||||
using expected_base = typename std::conditional<
|
||||
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>
|
||||
inline expected<T> make_expected(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));
|
||||
}
|
||||
|
||||
inline expected<void> make_expected(){
|
||||
return expected<void>();
|
||||
}
|
||||
|
||||
} //end of namespace std
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user