mirror of
https://github.com/TartanLlama/expected.git
synced 2025-08-03 02:44:30 +02:00
Fix #15
This commit is contained in:
@@ -22,6 +22,10 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
|
||||||
|
#define TL_EXPECTED_EXCEPTIONS_ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (defined(_MSC_VER) && _MSC_VER == 1900)
|
#if (defined(_MSC_VER) && _MSC_VER == 1900)
|
||||||
/// \exclude
|
/// \exclude
|
||||||
#define TL_EXPECTED_MSVC2015
|
#define TL_EXPECTED_MSVC2015
|
||||||
@@ -186,7 +190,7 @@ static constexpr unexpect_t unexpect{};
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename E>
|
template<typename E>
|
||||||
[[noreturn]] constexpr void throw_exception(E &&e) {
|
[[noreturn]] constexpr void throw_exception(E &&e) {
|
||||||
#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
|
#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
|
||||||
throw std::forward<E>(e);
|
throw std::forward<E>(e);
|
||||||
#else
|
#else
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@@ -196,7 +200,7 @@ template<typename E>
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TL_TRAITS_MUTEX
|
#ifndef TL_TRAITS_MUTEX
|
||||||
#define TL_TRAITS_MUTEX
|
#define TL_TRAITS_MUTEX
|
||||||
// C++14-style aliases for brevity
|
// C++14-style aliases for brevity
|
||||||
@@ -383,7 +387,7 @@ template <class T, class E> struct expected_storage_base<T, E, true, true> {
|
|||||||
|
|
||||||
~expected_storage_base() = default;
|
~expected_storage_base() = default;
|
||||||
union {
|
union {
|
||||||
char m_no_init;
|
char m_no_init;
|
||||||
T m_val;
|
T m_val;
|
||||||
unexpected<E> m_unexpect;
|
unexpected<E> m_unexpect;
|
||||||
};
|
};
|
||||||
@@ -429,7 +433,7 @@ template <class T, class E> struct expected_storage_base<T, E, true, false> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
union {
|
union {
|
||||||
char m_no_init;
|
char m_no_init;
|
||||||
T m_val;
|
T m_val;
|
||||||
unexpected<E> m_unexpect;
|
unexpected<E> m_unexpect;
|
||||||
};
|
};
|
||||||
@@ -473,7 +477,7 @@ template <class T, class E> struct expected_storage_base<T, E, false, true> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
union {
|
union {
|
||||||
char m_no_init;
|
char m_no_init;
|
||||||
T m_val;
|
T m_val;
|
||||||
unexpected<E> m_unexpect;
|
unexpected<E> m_unexpect;
|
||||||
};
|
};
|
||||||
@@ -539,7 +543,7 @@ template <class E> struct expected_storage_base<void, E, false, false> {
|
|||||||
|
|
||||||
struct dummy {};
|
struct dummy {};
|
||||||
union {
|
union {
|
||||||
char m_no_init;
|
char m_no_init;
|
||||||
dummy m_val;
|
dummy m_val;
|
||||||
unexpected<E> m_unexpect;
|
unexpected<E> m_unexpect;
|
||||||
};
|
};
|
||||||
@@ -568,6 +572,8 @@ struct expected_operations_base : expected_storage_base<T, E> {
|
|||||||
this->m_has_val = false;
|
this->m_has_val = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
|
||||||
|
|
||||||
// These assign overloads ensure that the most efficient assignment
|
// These assign overloads ensure that the most efficient assignment
|
||||||
// implementation is used while maintaining the strong exception guarantee.
|
// implementation is used while maintaining the strong exception guarantee.
|
||||||
// The problematic case is where rhs has a value, but *this does not.
|
// The problematic case is where rhs has a value, but *this does not.
|
||||||
@@ -658,6 +664,29 @@ struct expected_operations_base : expected_storage_base<T, E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// If exceptions are disabled then we can just copy-construct
|
||||||
|
void assign(const expected_operations_base &rhs) noexcept {
|
||||||
|
if (!this->m_has_val && rhs.m_has_val) {
|
||||||
|
geterr().~unexpected<E>();
|
||||||
|
construct(rhs.get());
|
||||||
|
} else {
|
||||||
|
assign_common(rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign(expected_operations_base &&rhs) noexcept {
|
||||||
|
if (!this->m_has_val && rhs.m_has_val) {
|
||||||
|
geterr().~unexpected<E>();
|
||||||
|
construct(std::move(rhs).get());
|
||||||
|
} else {
|
||||||
|
assign_common(rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// The common part of move/copy assigning
|
// The common part of move/copy assigning
|
||||||
template <class Rhs> void assign_common(Rhs &&rhs) {
|
template <class Rhs> void assign_common(Rhs &&rhs) {
|
||||||
if (this->m_has_val) {
|
if (this->m_has_val) {
|
||||||
@@ -1559,6 +1588,8 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
auto tmp = std::move(err());
|
auto tmp = std::move(err());
|
||||||
err().~unexpected<E>();
|
err().~unexpected<E>();
|
||||||
|
|
||||||
|
#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
|
||||||
try {
|
try {
|
||||||
::new (valptr()) T(std::move(v));
|
::new (valptr()) T(std::move(v));
|
||||||
this->m_has_val = true;
|
this->m_has_val = true;
|
||||||
@@ -1566,6 +1597,10 @@ public:
|
|||||||
err() = std::move(tmp);
|
err() = std::move(tmp);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
::new (valptr()) T(std::move(v));
|
||||||
|
this->m_has_val = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1623,6 +1658,7 @@ public:
|
|||||||
auto tmp = std::move(err());
|
auto tmp = std::move(err());
|
||||||
err().~unexpected<E>();
|
err().~unexpected<E>();
|
||||||
|
|
||||||
|
#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
|
||||||
try {
|
try {
|
||||||
::new (valptr()) T(std::forward<Args>(args)...);
|
::new (valptr()) T(std::forward<Args>(args)...);
|
||||||
this->m_has_val = true;
|
this->m_has_val = true;
|
||||||
@@ -1630,6 +1666,10 @@ public:
|
|||||||
err() = std::move(tmp);
|
err() = std::move(tmp);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
::new (valptr()) T(std::forward<Args>(args)...);
|
||||||
|
this->m_has_val = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1659,6 +1699,7 @@ public:
|
|||||||
auto tmp = std::move(err());
|
auto tmp = std::move(err());
|
||||||
err().~unexpected<E>();
|
err().~unexpected<E>();
|
||||||
|
|
||||||
|
#ifdef TL_EXPECTED_EXCEPTIONS_ENABLED
|
||||||
try {
|
try {
|
||||||
::new (valptr()) T(il, std::forward<Args>(args)...);
|
::new (valptr()) T(il, std::forward<Args>(args)...);
|
||||||
this->m_has_val = true;
|
this->m_has_val = true;
|
||||||
@@ -1666,6 +1707,10 @@ public:
|
|||||||
err() = std::move(tmp);
|
err() = std::move(tmp);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
::new (valptr()) T(il, std::forward<Args>(args)...);
|
||||||
|
this->m_has_val = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user