diff --git a/optional.hpp b/optional.hpp index 128d56c..20d176f 100644 --- a/optional.hpp +++ b/optional.hpp @@ -142,57 +142,27 @@ namespace tl { // [optional.relops], relational operators template inline constexpr bool operator==(const optional& lhs, const optional& rhs) { - if (lhs.has_value() != rhs.has_value()) - return false; - if (lhs.has_value()) - return true; - - return *lhs == *rhs; + return lhs.has_value() == rhs.has_value() && (!lhs.has_value() || *lhs == *rhs); } template inline constexpr bool operator!=(const optional& lhs, const optional& rhs) { - if (lhs.has_value() != rhs.has_value()) - return true; - if (lhs.has_value()) - return false; - - return *lhs != *rhs; + return lhs.has_value() != rhs.has_value() || (lhs.has_value() && *lhs != *rhs); } template inline constexpr bool operator<(const optional& lhs, const optional& rhs) { - if (!rhs.has_value()) - return false; - if (!lhs.has_value()) - return true; - - return *lhs < *rhs; + return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs); } template inline constexpr bool operator>(const optional& lhs, const optional& rhs) { - if (!lhs.has_value()) - return false; - if (!rhs.has_value()) - return true; - - return *lhs > *rhs; + return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs); } template inline constexpr bool operator<=(const optional& lhs, const optional& rhs) { - if (!lhs.has_value()) - return true; - if (!rhs.has_value()) - return false; - - return *lhs <= *rhs; + return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs); } template inline constexpr bool operator>=(const optional& lhs, const optional& rhs) { - if (!rhs.has_value()) - return true; - if (!lhs.has_value()) - return false; - - return *lhs >= *rhs; + return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs); } // [optional.nullops], comparison with nullopt @@ -313,6 +283,11 @@ namespace tl { struct optional_storage_base { constexpr optional_storage_base() noexcept : m_dummy(), m_has_value(false) {} + + template + constexpr optional_storage_base(in_place_t, U&& u) noexcept + : m_value(std::forward(u)), m_has_value(true) {} + ~optional_storage_base() { if (m_has_value) { m_value.~T(); @@ -333,6 +308,12 @@ namespace tl { struct optional_storage_base { constexpr optional_storage_base() noexcept : m_dummy(), m_has_value(false) {} + + + template + constexpr optional_storage_base(in_place_t, U&& u) noexcept + : m_value(std::forward(u)), m_has_value(true) {} + ~optional_storage_base() = default; struct dummy{}; @@ -347,6 +328,7 @@ namespace tl { template class optional : private detail::optional_storage_base { + using base = detail::optional_storage_base; public: using value_type = T; @@ -383,17 +365,11 @@ namespace tl { template ::value>* = nullptr, detail::enable_forward_value* = nullptr> - constexpr optional(U&& u) { - this->m_has_value = true; - new (std::addressof(this->m_value)) T (std::forward(u)); - } + constexpr optional(U&& u) : base(in_place, std::forward(u)) {} template ::value>* = nullptr, detail::enable_forward_value* = nullptr> - constexpr explicit optional(U&& u) { - this->m_has_value = true; - new (std::addressof(this->m_value)) T (std::forward(u)); - } + constexpr explicit optional(U&& u) : base(in_place, std::forward(u)) {} template * = nullptr, enable_if_t::value>* = nullptr>