This commit is contained in:
Baptiste Wicht 2016-09-25 21:30:44 +02:00
parent 4d95ac489e
commit 424e47a3aa

View File

@ -17,190 +17,214 @@
namespace std { namespace std {
constexpr struct only_set_valid_t {} only_set_valid; constexpr struct only_set_valid_t {
} only_set_valid;
template <typename E> template <typename E>
struct exceptional { struct exceptional {
typedef E error_type; using error_type = E; ///< The error type
error_type error; error_type error; ///< The error value
exceptional(): error() { exceptional()
: error() {
//Nothing else to init //Nothing else to init
} }
explicit exceptional(error_type e) : error(e) { explicit exceptional(error_type e)
: error(e) {
//Nothing else to init //Nothing else to init
} }
}; };
template<typename T, typename E> template <typename T, typename E>
union trivial_expected_storage { union trivial_expected_storage {
typedef T value_type; using value_type = T; ///< The value type
typedef E error_type; using error_type = E; ///< The error type
error_type error; error_type error; ///< The error value
value_type value; value_type value; ///< The value
constexpr trivial_expected_storage() : value(){ constexpr trivial_expected_storage()
: value() {
//Nothing else to init //Nothing else to init
} }
constexpr trivial_expected_storage(const exceptional<error_type>& e) : error(e.error){ constexpr trivial_expected_storage(const exceptional<error_type>& e)
: error(e.error) {
//Nothing else to init //Nothing else to init
} }
template<typename... Args> template <typename... Args>
constexpr trivial_expected_storage(Args&&... args): value(std::forward<Args>(args)...){ constexpr trivial_expected_storage(Args&&... args)
: value(std::forward<Args>(args)...) {
//Nothing else to init //Nothing else to init
} }
~trivial_expected_storage() = default; ~trivial_expected_storage() = default;
}; };
template<typename E> template <typename E>
union trivial_expected_storage <void, E> { union trivial_expected_storage<void, E> {
typedef void value_type; using value_type = Type; ///< The value type
typedef E error_type; using error_type = E; ///< The error type
error_type error; error_type error; ///< The error value
constexpr trivial_expected_storage() { constexpr trivial_expected_storage() {
//Nothing else to init //Nothing else to init
} }
constexpr trivial_expected_storage(const exceptional<error_type>& e) : error(e.error){ constexpr trivial_expected_storage(const exceptional<error_type>& e)
: error(e.error) {
//Nothing else to init //Nothing else to init
} }
~trivial_expected_storage() = default; ~trivial_expected_storage() = default;
}; };
template<typename T, typename E> template <typename T, typename E>
struct non_trivial_expected_storage { struct non_trivial_expected_storage {
typedef T value_type; using value_type = T; ///< The value type
typedef E error_type; using error_type = E; ///< The error type
error_type error; error_type error; ///< The error value
value_type value; value_type value; ///< The value
constexpr non_trivial_expected_storage() : value(){ constexpr non_trivial_expected_storage()
: value() {
//Nothing else to init //Nothing else to init
} }
constexpr non_trivial_expected_storage(const exceptional<error_type>& e) : error(e.error){ constexpr non_trivial_expected_storage(const exceptional<error_type>& e)
: error(e.error) {
//Nothing else to init //Nothing else to init
} }
template<typename... Args> template <typename... Args>
constexpr non_trivial_expected_storage(Args&&... args): value(std::forward<Args>(args)...){ constexpr non_trivial_expected_storage(Args&&... args)
: value(std::forward<Args>(args)...) {
//Nothing else to init //Nothing else to init
} }
~non_trivial_expected_storage() {}; ~non_trivial_expected_storage(){};
}; };
template<typename E> template <typename E>
struct non_trivial_expected_storage <void, E> { struct non_trivial_expected_storage<void, E> {
typedef void value_type; using value_type = Type; ///< The value type
typedef E error_type; using error_type = E; ///< The error type
error_type error; error_type error; ///< The error value
constexpr non_trivial_expected_storage(){ constexpr non_trivial_expected_storage() {
//Nothing else to init //Nothing else to init
} }
constexpr non_trivial_expected_storage(exceptional<error_type>& e) : error(e.error){ constexpr non_trivial_expected_storage(exceptional<error_type>& e)
: error(e.error) {
//Nothing else to init //Nothing else to init
} }
~non_trivial_expected_storage() {}; ~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; using value_type = T; ///< The value type
typedef E error_type; using error_type = E; ///< The error type
bool has_value; bool has_value; ///< Indicates if the base has a value
trivial_expected_storage<T, E> storage; trivial_expected_storage<T, E> storage;
trivial_expected_base() : has_value(true), storage(){ trivial_expected_base()
: has_value(true), storage() {
//Nothing else to init //Nothing else to init
} }
trivial_expected_base(only_set_valid_t, bool hv) : has_value(hv){ trivial_expected_base(only_set_valid_t, bool hv)
: has_value(hv) {
//Nothing else to init //Nothing else to init
} }
trivial_expected_base(const value_type& v) : has_value(true), storage(v){ trivial_expected_base(const value_type& v)
: has_value(true), storage(v) {
//Nothing else to init //Nothing else to init
} }
trivial_expected_base(value_type&& v) : has_value(true), storage(std::forward<value_type>(v)){ trivial_expected_base(value_type&& v)
: has_value(true), storage(std::forward<value_type>(v)) {
//Nothing else to init //Nothing else to init
} }
trivial_expected_base(const exceptional<error_type>& e) : has_value(false), storage(e) { trivial_expected_base(const exceptional<error_type>& e)
: has_value(false), storage(e) {
//Nothing else to init //Nothing else to init
} }
~trivial_expected_base() = default; ~trivial_expected_base() = default;
}; };
template<typename E> template <typename E>
struct trivial_expected_base <void, E> { struct trivial_expected_base<void, E> {
typedef E error_type; using error_type = E; ///< The error type
bool has_value; bool has_value; ///< Indicates if the base has a value
trivial_expected_storage<void, E> storage; trivial_expected_storage<void, E> storage;
trivial_expected_base() : has_value(true), storage(){ trivial_expected_base()
: has_value(true), storage() {
//Nothing else to init //Nothing else to init
} }
trivial_expected_base(only_set_valid_t, bool hv) : has_value(hv){ trivial_expected_base(only_set_valid_t, bool hv)
: has_value(hv) {
//Nothing else to init //Nothing else to init
} }
trivial_expected_base(const exceptional<error_type>& e) : has_value(false), storage(e) { trivial_expected_base(const exceptional<error_type>& e)
: has_value(false), storage(e) {
//Nothing else to init //Nothing else to init
} }
~trivial_expected_base() = default; ~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; using value_type = T; ///< The value type
typedef E error_type; using error_type = E; ///< The error type
bool has_value; bool has_value;
non_trivial_expected_storage<T, E> storage; non_trivial_expected_storage<T, E> storage;
non_trivial_expected_base() : has_value(true), storage(){ non_trivial_expected_base()
: has_value(true), storage() {
//Nothing else to init //Nothing else to init
} }
non_trivial_expected_base(only_set_valid_t, bool hv) : has_value(hv){ non_trivial_expected_base(only_set_valid_t, bool hv)
: has_value(hv) {
//Nothing else to init //Nothing else to init
} }
non_trivial_expected_base(const value_type& v) : has_value(true), storage(v){ non_trivial_expected_base(const value_type& v)
: has_value(true), storage(v) {
//Nothing else to init //Nothing else to init
} }
non_trivial_expected_base(value_type&& v) : has_value(true), storage(std::forward<value_type>(v)){ non_trivial_expected_base(value_type&& v)
: has_value(true), storage(std::forward<value_type>(v)) {
//Nothing else to init //Nothing else to init
} }
non_trivial_expected_base(const exceptional<error_type>& e) : has_value(false), storage(e) { non_trivial_expected_base(const exceptional<error_type>& e)
: has_value(false), storage(e) {
//Nothing else to init //Nothing else to init
} }
~non_trivial_expected_base(){ ~non_trivial_expected_base() {
if(has_value){ if (has_value) {
storage.value.~value_type(); storage.value.~value_type();
} else { } else {
storage.error.~error_type(); storage.error.~error_type();
@ -208,27 +232,30 @@ struct non_trivial_expected_base {
} }
}; };
template<typename E> template <typename E>
struct non_trivial_expected_base <void, E> { struct non_trivial_expected_base<void, E> {
typedef E error_type; using error_type = E; ///< The error type
bool has_value; bool has_value; ///< Indicates if the base has a value
non_trivial_expected_storage<void, E> storage; non_trivial_expected_storage<void, E> storage;
non_trivial_expected_base() : has_value(true), storage(){ non_trivial_expected_base()
: has_value(true), storage() {
//Nothing else to init //Nothing else to init
} }
non_trivial_expected_base(only_set_valid_t, bool hv) : has_value(hv){ non_trivial_expected_base(only_set_valid_t, bool hv)
: has_value(hv) {
//Nothing else to init //Nothing else to init
} }
non_trivial_expected_base(const exceptional<error_type>& e) : has_value(false), storage(e) { non_trivial_expected_base(const exceptional<error_type>& e)
: has_value(false), storage(e) {
//Nothing else to init //Nothing else to init
} }
~non_trivial_expected_base(){ ~non_trivial_expected_base() {
if(!has_value){ if (!has_value) {
storage.error.~error_type(); storage.error.~error_type();
} }
} }
@ -236,15 +263,14 @@ struct non_trivial_expected_base <void, E> {
template <typename T, typename E> template <typename T, typename E>
using expected_base = std::conditional_t< using expected_base = std::conditional_t<
std::is_trivially_destructible<T>::value && std::is_trivially_destructible<E>::value, std::is_trivially_destructible<T>::value && std::is_trivially_destructible<E>::value,
trivial_expected_base<T, E>, trivial_expected_base<T, E>,
non_trivial_expected_base<T, E> non_trivial_expected_base<T, E>>;
>;
template<typename T, typename E = size_t> template <typename T, typename E = size_t>
struct expected : expected_base<T, E> { struct expected : expected_base<T, E> {
typedef T value_type; using value_type = T; ///< The value type
typedef E error_type; using error_type = E; ///< The error type
typedef expected<T, E> this_type; typedef expected<T, E> this_type;
typedef expected_base<T, E> base_type; typedef expected_base<T, E> base_type;
@ -266,7 +292,7 @@ private:
return static_addressof(base_type::storage.error); return static_addressof(base_type::storage.error);
} }
constexpr const bool& contained_has_value() const& { constexpr const bool& contained_has_value() const & {
return base_type::has_value; return base_type::has_value;
} }
@ -278,7 +304,7 @@ private:
return std::move(base_type::has_value); return std::move(base_type::has_value);
} }
constexpr const value_type& contained_value() const& { constexpr const value_type& contained_value() const & {
return base_type::storage.value; return base_type::storage.value;
} }
@ -290,7 +316,7 @@ private:
return std::move(base_type::storage.value); return std::move(base_type::storage.value);
} }
constexpr const error_type& contained_error() const& { constexpr const error_type& contained_error() const & {
return base_type::storage.error; return base_type::storage.error;
} }
@ -305,64 +331,70 @@ private:
public: public:
/* Constructors */ /* Constructors */
constexpr expected(const value_type& v) : base_type(v){ constexpr expected(const value_type& v)
: base_type(v) {
//Nothing else to init //Nothing else to init
} }
constexpr expected(value_type&& v) : base_type(std::forward<value_type>(v)){ constexpr expected(value_type&& v)
: base_type(std::forward<value_type>(v)) {
//Nothing else to init //Nothing else to init
} }
expected(const expected& rhs) : base_type(only_set_valid, rhs.valid()) { expected(const expected& rhs)
if(rhs.valid()){ : base_type(only_set_valid, rhs.valid()) {
if (rhs.valid()) {
::new (value_ptr()) value_type(rhs.contained_value()); ::new (value_ptr()) value_type(rhs.contained_value());
} else { } else {
::new (error_ptr()) error_type(rhs.contained_error()); ::new (error_ptr()) error_type(rhs.contained_error());
} }
} }
expected(expected&& rhs) : base_type(only_set_valid, rhs.valid()) { expected(expected&& rhs)
if(rhs.valid()){ : base_type(only_set_valid, rhs.valid()) {
if (rhs.valid()) {
new (value_ptr()) value_type(std::move(rhs.contained_value())); new (value_ptr()) value_type(std::move(rhs.contained_value()));
} else { } else {
new (error_ptr()) error_type(std::move(rhs.contained_error())); new (error_ptr()) error_type(std::move(rhs.contained_error()));
} }
} }
expected(const exceptional<error_type>& e) : base_type(e) { expected(const exceptional<error_type>& e)
: base_type(e) {
//Nothing else to init //Nothing else to init
} }
expected() : base_type() {} expected()
: base_type() {}
~expected() = default; ~expected() = default;
/* Operators */ /* Operators */
expected& operator=(const expected& rhs){ expected& operator=(const expected& rhs) {
this_type(rhs).swap(*this); this_type(rhs).swap(*this);
return *this; return *this;
} }
expected& operator=(expected&& rhs){ expected& operator=(expected&& rhs) {
this_type(std::move(rhs)).swap(*this); this_type(std::move(rhs)).swap(*this);
return *this; return *this;
} }
expected& operator=(const value_type& v){ expected& operator=(const value_type& v) {
this_type(v).swap(*this); this_type(v).swap(*this);
return *this; return *this;
} }
expected& operator=(value_type&& v){ expected& operator=(value_type&& v) {
this_type(std::move(v)).swap(*this); this_type(std::move(v)).swap(*this);
return *this; return *this;
} }
/* Swap */ /* Swap */
void swap(expected& rhs){ void swap(expected& rhs) {
if (valid()){ if (valid()) {
if (rhs.valid()){ if (rhs.valid()) {
std::swap(contained_value(), rhs.contained_value()); std::swap(contained_value(), rhs.contained_value());
} else { } else {
error_type t = std::move(rhs.contained_error()); error_type t = std::move(rhs.contained_error());
@ -371,7 +403,7 @@ public:
std::swap(contained_has_value(), rhs.contained_has_value()); std::swap(contained_has_value(), rhs.contained_has_value());
} }
} else { } else {
if (rhs.valid()){ if (rhs.valid()) {
rhs.swap(*this); rhs.swap(*this);
} else { } else {
std::swap(contained_error(), rhs.contained_error()); std::swap(contained_error(), rhs.contained_error());
@ -393,11 +425,11 @@ public:
return contained_value(); return contained_value();
} }
constexpr const value_type& operator*() const { constexpr const value_type& operator*() const {
return contained_value(); return contained_value();
} }
value_type& operator*(){ value_type& operator*() {
return contained_value(); return contained_value();
} }
@ -405,7 +437,7 @@ public:
return value_ptr(); return value_ptr();
} }
value_type* operator->(){ value_type* operator->() {
return value_ptr(); return value_ptr();
} }
@ -422,10 +454,10 @@ public:
} }
}; };
template<typename E> template <typename E>
struct expected <void, E> : expected_base<void, E> { struct expected<void, E> : expected_base<void, E> {
typedef void value_type; using value_type = void; ///< The value type
typedef E error_type; using error_type = E; ///< The error type
typedef expected<void, E> this_type; typedef expected<void, E> this_type;
typedef expected_base<void, E> base_type; typedef expected_base<void, E> base_type;
@ -439,7 +471,7 @@ private:
return static_addressof(base_type::storage.error); return static_addressof(base_type::storage.error);
} }
constexpr const bool& contained_has_value() const& { constexpr const bool& contained_has_value() const & {
return base_type::has_value; return base_type::has_value;
} }
@ -451,7 +483,7 @@ private:
return std::move(base_type::has_value); return std::move(base_type::has_value);
} }
constexpr const error_type& contained_error() const& { constexpr const error_type& contained_error() const & {
return base_type::storage.error; return base_type::storage.error;
} }
@ -466,47 +498,51 @@ private:
public: public:
/* Constructors */ /* Constructors */
expected(const expected& rhs) : base_type(only_set_valid, rhs.valid()) { expected(const expected& rhs)
if(!rhs.valid()){ : base_type(only_set_valid, rhs.valid()) {
if (!rhs.valid()) {
::new (error_ptr()) error_type(rhs.contained_error()); ::new (error_ptr()) error_type(rhs.contained_error());
} }
} }
expected(expected&& rhs) : base_type(only_set_valid, rhs.valid()) { expected(expected&& rhs)
if(!rhs.valid()){ : base_type(only_set_valid, rhs.valid()) {
if (!rhs.valid()) {
new (error_ptr()) error_type(std::move(rhs.contained_error())); new (error_ptr()) error_type(std::move(rhs.contained_error()));
} }
} }
expected(const exceptional<error_type>& e) : base_type(e) { expected(const exceptional<error_type>& e)
: base_type(e) {
//Nothing else to init //Nothing else to init
} }
expected() : base_type() {} expected()
: base_type() {}
~expected() = default; ~expected() = default;
/* Operators */ /* Operators */
expected& operator=(const expected& rhs){ expected& operator=(const expected& rhs) {
this_type(rhs).swap(*this); this_type(rhs).swap(*this);
return *this; return *this;
} }
expected& operator=(expected&& rhs){ expected& operator=(expected&& rhs) {
this_type(std::move(rhs)).swap(*this); this_type(std::move(rhs)).swap(*this);
return *this; return *this;
} }
/* Swap */ /* Swap */
void swap(expected& rhs){ void swap(expected& rhs) {
if (valid()){ if (valid()) {
if (!rhs.valid()){ if (!rhs.valid()) {
error_type t = std::move(rhs.contained_error()); error_type t = std::move(rhs.contained_error());
new (error_ptr()) error_type(t); new (error_ptr()) error_type(t);
} }
} else { } else {
if (!rhs.valid()){ if (!rhs.valid()) {
std::swap(contained_error(), rhs.contained_error()); std::swap(contained_error(), rhs.contained_error());
} }
} }
@ -535,41 +571,41 @@ public:
} }
}; };
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));
} }
template<typename T> template <typename T>
inline expected<T> make_expected(const T& v){ inline expected<T> make_expected(const T& v) {
return expected<T>(v); return expected<T>(v);
} }
template<typename T, typename U, typename E> template <typename T, typename U, typename E>
inline expected<T, U> make_expected_from_error(E v){ inline expected<T, U> make_expected_from_error(E v) {
return expected<T, U>(exceptional<U>(v)); return expected<T, U>(exceptional<U>(v));
} }
template<typename T, typename E> template <typename T, typename E>
inline expected<T, E> make_expected_from_error(E v){ inline expected<T, E> make_expected_from_error(E v) {
return expected<T, E>(exceptional<E>(v)); return expected<T, E>(exceptional<E>(v));
} }
template<typename T, typename E> template <typename T, typename E>
inline expected<T, E> make_unexpected(E v){ inline expected<T, E> make_unexpected(E v) {
return expected<T, E>(exceptional<E>(v)); return expected<T, E>(exceptional<E>(v));
} }
template<typename E> template <typename E>
inline expected<void, E> make_expected_zero(E v){ inline expected<void, E> make_expected_zero(E v) {
if(v){ if (v) {
return expected<void, E>(exceptional<E>(v)); return expected<void, E>(exceptional<E>(v));
} else { } else {
return expected<void, E>(); return expected<void, E>();
} }
} }
inline expected<void> make_expected(){ inline expected<void> make_expected() {
return expected<void>(); return expected<void>();
} }