diff --git a/optional.hpp b/optional.hpp index 8b43bd2..7b66f23 100644 --- a/optional.hpp +++ b/optional.hpp @@ -397,12 +397,95 @@ class optional : private detail::optional_storage_base { ~optional() = default; // [optional.assign], assignment - optional& operator=(nullopt_t) noexcept; - optional& operator=(const optional&); - optional& operator=(optional&&) noexcept; - template optional& operator=(U&&); - template optional& operator=(const optional&); - template optional& operator=(optional&&); + optional& operator=(nullopt_t) noexcept { + if (has_value()) { + this->m_value.~T(); + this->m_has_value = false; + } + } + + // TODO conditionally delete, check exception guarantee + optional& operator=(const optional& rhs) { + if (has_value()) { + if (rhs.has_value()) { + this->m_value = rhs.m_value; + } + else { + this->m_value.~T(); + this->m_has_value = false; + } + } + + if (rhs.has_value()) { + new (std::addressof(this->m_value)) T (rhs.m_value); + this->m_has_value = true; + } + } + + // TODO conditionally delete, check exception guarantee + optional& operator=(optional&& rhs) noexcept { + if (has_value()) { + if (rhs.has_value()) { + this->m_value = std::move(rhs.m_value); + } + else { + this->m_value.~T(); + this->m_has_value = false; + } + } + + if (rhs.has_value()) { + new (std::addressof(this->m_value)) T (std::move(rhs.m_value)); + this->m_has_value = true; + } + } + + // TODO conditionally delete, check exception guarantee + template optional& operator=(U&& u) { + if (has_value()) { + this->m_value = std::forward(u); + } + else { + new (std::addressof(this->m_value)) T (std::forward(u)); + this->m_has_value = true; + } + } + + // TODO SFINAE, check exception guarantee + template optional& operator=(const optional& rhs) { + if (has_value()) { + if (rhs.has_value()) { + this->m_value = rhs.m_value; + } + else { + this->m_value.~T(); + this->m_has_value = false; + } + } + + if (rhs.has_value()) { + new (std::addressof(this->m_value)) T (rhs.m_value); + this->m_has_value = true; + } + } + + // TODO SFINAE, check exception guarantee + template optional& operator=(optional&& rhs) { + if (has_value()) { + if (rhs.has_value()) { + this->m_value = std::move(rhs.m_value); + } + else { + this->m_value.~T(); + this->m_has_value = false; + } + } + + if (rhs.has_value()) { + new (std::addressof(this->m_value)) T (std::move(rhs.m_value)); + this->m_has_value = true; + } + } template T& emplace(Args&&... args) { static_assert(std::is_constructible::value,