#include #include TEST(Optional, Noexcept) { m5::stl::optional o1{4}; m5::stl::optional o2{42}; { SCOPED_TRACE("comparison with nullopt"); EXPECT_TRUE(noexcept(o1 == m5::stl::nullopt)); EXPECT_TRUE(noexcept(m5::stl::nullopt == o1)); EXPECT_TRUE(noexcept(o1 != m5::stl::nullopt)); EXPECT_TRUE(noexcept(m5::stl::nullopt != o1)); EXPECT_TRUE(noexcept(o1 < m5::stl::nullopt)); EXPECT_TRUE(noexcept(m5::stl::nullopt < o1)); EXPECT_TRUE(noexcept(o1 <= m5::stl::nullopt)); EXPECT_TRUE(noexcept(m5::stl::nullopt <= o1)); EXPECT_TRUE(noexcept(o1 > m5::stl::nullopt)); EXPECT_TRUE(noexcept(m5::stl::nullopt > o1)); EXPECT_TRUE(noexcept(o1 >= m5::stl::nullopt)); EXPECT_TRUE(noexcept(m5::stl::nullopt >= o1)); } { SCOPED_TRACE("swap"); // TODO see why this fails #if !defined(_MSC_VER) || _MSC_VER > 1900 EXPECT_TRUE(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; } }; m5::stl::optional ont; m5::stl::optional ot; EXPECT_TRUE(noexcept(ont.swap(ont))); EXPECT_TRUE(!noexcept(ot.swap(ot))); #endif } { SCOPED_TRACE("constructors"); // TODO see why this fails #if !defined(_MSC_VER) || _MSC_VER > 1900 EXPECT_TRUE(noexcept(m5::stl::optional{})); EXPECT_TRUE(noexcept(m5::stl::optional{m5::stl::nullopt})); struct nothrow_move { nothrow_move(nothrow_move &&) noexcept = default; }; struct throw_move { throw_move(throw_move &&) { } }; using nothrow_opt = m5::stl::optional; using throw_opt = m5::stl::optional; EXPECT_TRUE(std::is_nothrow_move_constructible::value); EXPECT_TRUE(!std::is_nothrow_move_constructible::value); #endif } { SCOPED_TRACE("assignment"); EXPECT_TRUE(noexcept(o1 = m5::stl::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 = m5::stl::optional; using throw_opt = m5::stl::optional; EXPECT_TRUE(noexcept(std::declval() = std::declval())); EXPECT_TRUE(!noexcept(std::declval() = std::declval())); } { SCOPED_TRACE("observers"); EXPECT_TRUE(noexcept(static_cast(o1))); EXPECT_TRUE(noexcept(o1.has_value())); } { SCOPED_TRACE("modifiers"); EXPECT_TRUE(noexcept(o1.reset())); } }