blob: edfa88f0c6876344f8297466a3eac8361bf1f3cd [file] [log] [blame]
Brian Silvermanda861352019-02-02 16:42:28 -08001#include "catch.hpp"
2#include "optional.hpp"
3
4TEST_CASE("Noexcept", "[noexcept]") {
5 tl::optional<int> o1{4};
6 tl::optional<int> o2{42};
7
8 SECTION("comparison with nullopt") {
9 REQUIRE(noexcept(o1 == tl::nullopt));
10 REQUIRE(noexcept(tl::nullopt == o1));
11 REQUIRE(noexcept(o1 != tl::nullopt));
12 REQUIRE(noexcept(tl::nullopt != o1));
13 REQUIRE(noexcept(o1 < tl::nullopt));
14 REQUIRE(noexcept(tl::nullopt < o1));
15 REQUIRE(noexcept(o1 <= tl::nullopt));
16 REQUIRE(noexcept(tl::nullopt <= o1));
17 REQUIRE(noexcept(o1 > tl::nullopt));
18 REQUIRE(noexcept(tl::nullopt > o1));
19 REQUIRE(noexcept(o1 >= tl::nullopt));
20 REQUIRE(noexcept(tl::nullopt >= o1));
21 }
22
23 SECTION("swap") {
24 //TODO see why this fails
25#if !defined(_MSC_VER) || _MSC_VER > 1900
26 REQUIRE(noexcept(swap(o1, o2)) == noexcept(o1.swap(o2)));
27
28 struct nothrow_swappable {
29 nothrow_swappable &swap(const nothrow_swappable &) noexcept {
30 return *this;
31 }
32 };
33
34 struct throw_swappable {
35 throw_swappable() = default;
36 throw_swappable(const throw_swappable &) {}
37 throw_swappable(throw_swappable &&) {}
38 throw_swappable &swap(const throw_swappable &) { return *this; }
39 };
40
41 tl::optional<nothrow_swappable> ont;
42 tl::optional<throw_swappable> ot;
43
44 REQUIRE(noexcept(ont.swap(ont)));
45 REQUIRE(!noexcept(ot.swap(ot)));
46 #endif
47 }
48
49 SECTION("constructors") {
50 //TODO see why this fails
51#if !defined(_MSC_VER) || _MSC_VER > 1900
52 REQUIRE(noexcept(tl::optional<int>{}));
53 REQUIRE(noexcept(tl::optional<int>{tl::nullopt}));
54
55 struct nothrow_move {
56 nothrow_move(nothrow_move &&) noexcept = default;
57 };
58
59 struct throw_move {
60 throw_move(throw_move &&){};
61 };
62
63 using nothrow_opt = tl::optional<nothrow_move>;
64 using throw_opt = tl::optional<throw_move>;
65
66 REQUIRE(std::is_nothrow_move_constructible<nothrow_opt>::value);
67 REQUIRE(!std::is_nothrow_move_constructible<throw_opt>::value);
68#endif
69 }
70
71 SECTION("assignment") {
72 REQUIRE(noexcept(o1 = tl::nullopt));
73
74 struct nothrow_move_assign {
75 nothrow_move_assign() = default;
76 nothrow_move_assign(nothrow_move_assign &&) noexcept = default;
77 nothrow_move_assign &operator=(const nothrow_move_assign &) = default;
78 };
79
80 struct throw_move_assign {
81 throw_move_assign() = default;
82 throw_move_assign(throw_move_assign &&){};
83 throw_move_assign &operator=(const throw_move_assign &) { return *this; }
84 };
85
86 using nothrow_opt = tl::optional<nothrow_move_assign>;
87 using throw_opt = tl::optional<throw_move_assign>;
88
89 REQUIRE(
90 noexcept(std::declval<nothrow_opt>() = std::declval<nothrow_opt>()));
91 REQUIRE(!noexcept(std::declval<throw_opt>() = std::declval<throw_opt>()));
92 }
93
94 SECTION("observers") {
95 REQUIRE(noexcept(static_cast<bool>(o1)));
96 REQUIRE(noexcept(o1.has_value()));
97 }
98
99 SECTION("modifiers") { REQUIRE(noexcept(o1.reset())); }
100}