Files
optional/tests/noexcept.cpp

101 lines
2.9 KiB
C++
Raw Normal View History

2017-10-02 08:57:11 +01:00
#include "catch.hpp"
2017-10-02 09:16:58 +01:00
#include "optional.hpp"
2017-10-02 08:57:11 +01:00
TEST_CASE("Noexcept", "[noexcept]") {
2017-10-02 09:16:58 +01:00
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") {
2017-10-20 11:34:22 +01:00
//TODO see why this fails
#if !defined(_MSC_VER) || _MSC_VER >= 1900
2017-10-02 09:16:58 +01:00
REQUIRE(noexcept(swap(o1, o2)) == noexcept(o1.swap(o2)));
struct nothrow_swappable {
nothrow_swappable &swap(const nothrow_swappable &) noexcept {
return *this;
}
};
struct throw_swappable {
2017-10-20 11:28:34 +01:00
throw_swappable() = default;
throw_swappable(const throw_swappable &) {}
2017-10-02 11:18:15 +01:00
throw_swappable(throw_swappable &&) {}
2017-10-02 09:16:58 +01:00
throw_swappable &swap(const throw_swappable &) { return *this; }
};
2017-10-02 11:18:15 +01:00
tl::optional<nothrow_swappable> ont;
tl::optional<throw_swappable> ot;
REQUIRE(noexcept(ont.swap(ont)));
REQUIRE(!noexcept(ot.swap(ot)));
2017-10-20 12:13:45 +01:00
#endif
2017-10-02 09:16:58 +01:00
}
SECTION("constructors") {
2017-10-20 12:13:45 +01:00
//TODO see why this fails
#if !defined(_MSC_VER) || _MSC_VER >= 1900
2017-10-02 09:16:58 +01:00
REQUIRE(noexcept(tl::optional<int>{}));
REQUIRE(noexcept(tl::optional<int>{tl::nullopt}));
2017-10-02 08:57:11 +01:00
2017-10-02 09:16:58 +01:00
struct nothrow_move {
nothrow_move(nothrow_move &&) noexcept = default;
};
2017-10-02 08:57:11 +01:00
2017-10-02 09:16:58 +01:00
struct throw_move {
2017-10-02 11:18:15 +01:00
throw_move(throw_move &&){};
2017-10-02 09:16:58 +01:00
};
2017-10-02 11:18:15 +01:00
using nothrow_opt = tl::optional<nothrow_move>;
using throw_opt = tl::optional<throw_move>;
2017-11-01 19:03:45 +00:00
REQUIRE(std::is_nothrow_move_constructible<nothrow_opt>::value);
REQUIRE(!std::is_nothrow_move_constructible<throw_opt>::value);
2017-10-20 12:13:45 +01:00
#endif
2017-10-02 09:16:58 +01:00
}
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 &&){};
2018-04-11 15:54:58 +01:00
throw_move_assign &operator=(const throw_move_assign &) { return *this; }
2017-10-02 09:16:58 +01:00
};
2017-10-02 11:18:15 +01:00
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>()));
2017-10-02 09:16:58 +01:00
}
SECTION("observers") {
REQUIRE(noexcept(static_cast<bool>(o1)));
REQUIRE(noexcept(o1.has_value()));
}
2017-10-02 11:18:15 +01:00
SECTION("modifiers") { REQUIRE(noexcept(o1.reset())); }
2017-10-02 09:16:58 +01:00
}