From 084a9001f4e8bdb0fc257d772bf03621c9ee3260 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Mon, 8 Jul 2019 19:35:48 +0900 Subject: [PATCH 1/3] Add missing noexcept specifications to methods of optional --- include/tl/optional.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/tl/optional.hpp b/include/tl/optional.hpp index 4d41e54..9cba0b8 100644 --- a/include/tl/optional.hpp +++ b/include/tl/optional.hpp @@ -1939,12 +1939,12 @@ public: template >::value> * = nullptr> - constexpr optional(U &&u) : m_value(std::addressof(u)) { + constexpr optional(U &&u) noexcept : m_value(std::addressof(u)) { static_assert(std::is_lvalue_reference::value, "U must be an lvalue"); } template - constexpr explicit optional(const optional &rhs) : optional(*rhs) {} + constexpr explicit optional(const optional &rhs) noexcept : optional(*rhs) {} /// No-op ~optional() = default; @@ -1977,7 +1977,7 @@ public: /// /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise /// resets the stored value in `*this`. - template optional &operator=(const optional &rhs) { + template optional &operator=(const optional &rhs) noexcept { m_value = std::addressof(rhs.value()); return *this; } @@ -1996,14 +1996,14 @@ public: void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); } /// Returns a pointer to the stored value - constexpr const T *operator->() const { return m_value; } + constexpr const T *operator->() const noexcept { return m_value; } - TL_OPTIONAL_11_CONSTEXPR T *operator->() { return m_value; } + TL_OPTIONAL_11_CONSTEXPR T *operator->() noexcept { return m_value; } /// Returns the stored value - TL_OPTIONAL_11_CONSTEXPR T &operator*() { return *m_value; } + TL_OPTIONAL_11_CONSTEXPR T &operator*() noexcept { return *m_value; } - constexpr const T &operator*() const { return *m_value; } + constexpr const T &operator*() const noexcept { return *m_value; } constexpr bool has_value() const noexcept { return m_value != nullptr; } @@ -2024,7 +2024,7 @@ public: } /// Returns the stored value if there is one, otherwise returns `u` - template constexpr T value_or(U &&u) const & { + template constexpr T value_or(U &&u) const & noexcept { static_assert(std::is_copy_constructible::value && std::is_convertible::value, "T must be copy constructible and convertible from U"); @@ -2032,7 +2032,7 @@ public: } /// \group value_or - template TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && { + template TL_OPTIONAL_11_CONSTEXPR T value_or(U &&u) && noexcept { static_assert(std::is_move_constructible::value && std::is_convertible::value, "T must be move constructible and convertible from U"); From b074bee4096ef174c5f966fa4a6e046dad956c0d Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Mon, 8 Jul 2019 19:32:17 +0900 Subject: [PATCH 2/3] Fix implementation of optional::emplace() --- include/tl/optional.hpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/include/tl/optional.hpp b/include/tl/optional.hpp index 9cba0b8..ad8ae2f 100644 --- a/include/tl/optional.hpp +++ b/include/tl/optional.hpp @@ -1982,15 +1982,12 @@ public: return *this; } - /// Constructs the value in-place, destroying the current one if there is - /// one. - template T &emplace(Args &&... args) noexcept { - static_assert(std::is_constructible::value, - "T must be constructible with Args"); - - *this = nullopt; - this->construct(std::forward(args)...); - return value(); + /// Rebinds this optional to `u`. + template >::value> + * = nullptr> + optional &emplace(U &&u) noexcept { + return *this = std::forward(u); } void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); } From ce266d52807c0d9d78d946c86267422193c6dd11 Mon Sep 17 00:00:00 2001 From: Simon Brand Date: Mon, 8 Jul 2019 11:49:21 +0100 Subject: [PATCH 3/3] Add test --- tests/issues.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/issues.cpp b/tests/issues.cpp index d5672a3..1f465e1 100644 --- a/tests/issues.cpp +++ b/tests/issues.cpp @@ -31,4 +31,15 @@ TEST_CASE("issue 15") { o = o; REQUIRE(o->value == 42); +} + +TEST_CASE("issue 33") { + int i = 0; + int j = 0; + tl::optional a = i; + a.emplace(j); + *a = 42; + REQUIRE(j == 42); + REQUIRE(*a == 42); + REQUIRE(a.has_value()); } \ No newline at end of file