119 lines
3.7 KiB
C++
119 lines
3.7 KiB
C++
#include <gtest/gtest.h>
|
|
#include <m5_utility/stl/optional.hpp>
|
|
|
|
TEST(Optional, Noexcept)
|
|
{
|
|
m5::stl::optional<int> o1{4};
|
|
m5::stl::optional<int> 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<nothrow_swappable> ont;
|
|
m5::stl::optional<throw_swappable> 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<int>{}));
|
|
EXPECT_TRUE(noexcept(m5::stl::optional<int>{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<nothrow_move>;
|
|
using throw_opt = m5::stl::optional<throw_move>;
|
|
|
|
EXPECT_TRUE(std::is_nothrow_move_constructible<nothrow_opt>::value);
|
|
EXPECT_TRUE(!std::is_nothrow_move_constructible<throw_opt>::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<nothrow_move_assign>;
|
|
using throw_opt = m5::stl::optional<throw_move_assign>;
|
|
|
|
EXPECT_TRUE(noexcept(std::declval<nothrow_opt>() = std::declval<nothrow_opt>()));
|
|
EXPECT_TRUE(!noexcept(std::declval<throw_opt>() = std::declval<throw_opt>()));
|
|
}
|
|
{
|
|
SCOPED_TRACE("observers");
|
|
EXPECT_TRUE(noexcept(static_cast<bool>(o1)));
|
|
EXPECT_TRUE(noexcept(o1.has_value()));
|
|
}
|
|
{
|
|
SCOPED_TRACE("modifiers");
|
|
EXPECT_TRUE(noexcept(o1.reset()));
|
|
}
|
|
}
|