Squashed 'third_party/optional/' content from commit 1baad184f
Change-Id: I9b2473a84dcf6d9892f1f7a9fd21b340796b6ff5
git-subtree-dir: third_party/optional
git-subtree-split: 1baad184f022a3a7502db094a984a86adedf9626
diff --git a/tests/noexcept.cpp b/tests/noexcept.cpp
new file mode 100644
index 0000000..edfa88f
--- /dev/null
+++ b/tests/noexcept.cpp
@@ -0,0 +1,100 @@
+#include "catch.hpp"
+#include "optional.hpp"
+
+TEST_CASE("Noexcept", "[noexcept]") {
+ tl::optional<int> o1{4};
+ tl::optional<int> 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("swap") {
+ //TODO see why this fails
+#if !defined(_MSC_VER) || _MSC_VER > 1900
+ 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() = default;
+ throw_swappable(const throw_swappable &) {}
+ throw_swappable(throw_swappable &&) {}
+ throw_swappable &swap(const throw_swappable &) { return *this; }
+ };
+
+ tl::optional<nothrow_swappable> ont;
+ tl::optional<throw_swappable> ot;
+
+ REQUIRE(noexcept(ont.swap(ont)));
+ REQUIRE(!noexcept(ot.swap(ot)));
+ #endif
+ }
+
+ SECTION("constructors") {
+ //TODO see why this fails
+#if !defined(_MSC_VER) || _MSC_VER > 1900
+ REQUIRE(noexcept(tl::optional<int>{}));
+ REQUIRE(noexcept(tl::optional<int>{tl::nullopt}));
+
+ struct nothrow_move {
+ nothrow_move(nothrow_move &&) noexcept = default;
+ };
+
+ struct throw_move {
+ throw_move(throw_move &&){};
+ };
+
+ using nothrow_opt = tl::optional<nothrow_move>;
+ using throw_opt = tl::optional<throw_move>;
+
+ REQUIRE(std::is_nothrow_move_constructible<nothrow_opt>::value);
+ REQUIRE(!std::is_nothrow_move_constructible<throw_opt>::value);
+#endif
+ }
+
+ 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 &) { return *this; }
+ };
+
+ using nothrow_opt = tl::optional<nothrow_move_assign>;
+ using throw_opt = tl::optional<throw_move_assign>;
+
+ REQUIRE(
+ noexcept(std::declval<nothrow_opt>() = std::declval<nothrow_opt>()));
+ REQUIRE(!noexcept(std::declval<throw_opt>() = std::declval<throw_opt>()));
+ }
+
+ SECTION("observers") {
+ REQUIRE(noexcept(static_cast<bool>(o1)));
+ REQUIRE(noexcept(o1.has_value()));
+ }
+
+ SECTION("modifiers") { REQUIRE(noexcept(o1.reset())); }
+}