This commit is contained in:
Simon Brand
2018-05-15 18:59:33 +01:00
parent 3e26d2eefc
commit 2afad949d0

View File

@@ -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
@@ -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
} }
} }