diff --git a/tests/noexcept.cpp b/tests/noexcept.cpp index b3cd702..03e3242 100644 --- a/tests/noexcept.cpp +++ b/tests/noexcept.cpp @@ -1,29 +1,89 @@ -#include "optional.hpp" #include "catch.hpp" +#include "optional.hpp" TEST_CASE("Noexcept", "[noexcept]") { - tl::optional o1 {4}; - tl::optional o2 {42}; + tl::optional o1{4}; + tl::optional o2{42}; - SECTION ("comparison with nullopt") { - REQUIRE(noexcept(o1 == tl::nullopt)); - REQUIRE(noexcept(tl::nullopt == o1)); - REQUIRE(noexcept(o1 != tl::nullopt)); - REQUIRE(noexcept(tl::nullopt != o1)); - REQUIRE(noexcept(o1 < tl::nullopt)); - REQUIRE(noexcept(tl::nullopt < o1)); - REQUIRE(noexcept(o1 <= tl::nullopt)); - REQUIRE(noexcept(tl::nullopt <= o1)); - REQUIRE(noexcept(o1 > tl::nullopt)); - REQUIRE(noexcept(tl::nullopt > o1)); - REQUIRE(noexcept(o1 >= tl::nullopt)); - REQUIRE(noexcept(tl::nullopt >= o1)); - } + SECTION("comparison with nullopt") { + REQUIRE(noexcept(o1 == tl::nullopt)); + REQUIRE(noexcept(tl::nullopt == o1)); + REQUIRE(noexcept(o1 != tl::nullopt)); + REQUIRE(noexcept(tl::nullopt != o1)); + REQUIRE(noexcept(o1 < tl::nullopt)); + REQUIRE(noexcept(tl::nullopt < o1)); + REQUIRE(noexcept(o1 <= tl::nullopt)); + REQUIRE(noexcept(tl::nullopt <= o1)); + REQUIRE(noexcept(o1 > tl::nullopt)); + REQUIRE(noexcept(tl::nullopt > o1)); + REQUIRE(noexcept(o1 >= tl::nullopt)); + REQUIRE(noexcept(tl::nullopt >= o1)); + } - SECTION ("swap") { - REQUIRE(tl::detail::is_swappable::value); - //REQUIRE(noexcept(swap(o1,o2)) == noexcept(o1.swap(o2))); - } + SECTION("swap") { + REQUIRE(noexcept(swap(o1, o2)) == noexcept(o1.swap(o2))); + + struct nothrow_swappable { + nothrow_swappable &swap(const nothrow_swappable &) noexcept { + return *this; + } + }; + + struct throw_swappable { + throw_swappable &swap(const throw_swappable &) { return *this; } + }; + + REQUIRE(noexcept(std::declval().swap( + std::declval()))); + REQUIRE(!noexcept( + std::declval().swap(std::declval()))); + } + + SECTION("constructors") { + REQUIRE(noexcept(tl::optional{})); + REQUIRE(noexcept(tl::optional{tl::nullopt})); + + struct nothrow_move { + nothrow_move() = default; + nothrow_move(nothrow_move &&) noexcept = default; + }; + + struct throw_move { + throw_move() = default; + throw_move(throw_move &&) = default; + }; + + REQUIRE(noexcept(tl::optional{std::declval()})); + REQUIRE(!noexcept(tl::optional{std::declval()})); + } + + SECTION("assignment") { + REQUIRE(noexcept(o1 = tl::nullopt)); + + struct nothrow_move_assign { + nothrow_move_assign() = default; + nothrow_move_assign(nothrow_move_assign &&) noexcept = default; + nothrow_move_assign &operator=(const nothrow_move_assign &) = default; + }; + + struct throw_move_assign { + throw_move_assign() = default; + throw_move_assign(throw_move_assign &&){}; + throw_move_assign &operator=(const throw_move_assign &) {} + }; + + REQUIRE(noexcept(std::declval() = + std::declval())); + REQUIRE(!noexcept(std::declval() = + std::declval())); + } + + SECTION("observers") { + REQUIRE(noexcept(static_cast(o1))); + REQUIRE(noexcept(o1.has_value())); + } + + SECTION("modifiers") { + REQUIRE(noexcept(o1.reset())); + } } - -