blob: fb957a7ad3d361defc93851cc3f37d172d3152da [file]
// { dg-do run { target c++26 } }
#include <memory>
#include <testsuite_hooks.h>
struct Obj
{
int i;
constexpr auto operator<=>(const Obj&) const = default;
};
template<>
struct std::hash<Obj>
{
static size_t operator()(Obj const& obj)
{ return std::hash<int>{}(obj.i); }
};
constexpr void
test_relops()
{
std::indirect<Obj> i1;
VERIFY( i1 == i1 );
VERIFY( i1 <= i1 );
VERIFY( i1 >= i1 );
std::indirect<Obj> i2 = std::move(i1); // make i1 valueless
VERIFY( i1 == i1 );
VERIFY( i2 == i2 );
VERIFY( i2 != i1 );
VERIFY( i1 < i2 );
VERIFY( i2 >= i1 );
std::indirect<Obj> i3 = std::move(i2); // make i2 valueless
VERIFY( i2 == i1 );
VERIFY( i2 >= i1 );
VERIFY( i2 <= i1 );
VERIFY( i3 > i2 );
}
constexpr void
test_comp_with_t()
{
std::indirect<Obj> i1;
Obj o{2};
VERIFY( i1 != o );
VERIFY( i1 < o );
std::indirect<Obj> i2(Obj{2});
VERIFY( i2 == o );
VERIFY( i2 <= o );
VERIFY( o <= i2 );
std::indirect<Obj> i3 = std::move(i2); // make i2 valueless
VERIFY( i2 != o );
VERIFY( i2 < o );
}
void
test_hash()
{
Obj o{5};
std::indirect<Obj> i(o);
VERIFY( std::hash<std::indirect<Obj>>{}(i)
== std::hash<Obj>{}(o) );
auto(std::move(i)); // make i valueless
(void)std::hash<std::indirect<Obj>>{}(i);
}
template<bool Noexcept>
struct BoolConv
{
bool b;
constexpr BoolConv(bool p) noexcept
: b(p)
{ }
constexpr operator bool() const noexcept(Noexcept)
{ return b; }
};
template<bool Noexcept, typename EqRet = bool>
struct Comp
{
friend constexpr EqRet
operator==(const Comp&, const Comp&) noexcept(Noexcept)
{ return true; }
friend constexpr std::strong_ordering
operator<=>(const Comp&, const Comp&) noexcept(Noexcept)
{ return std::strong_ordering::equal; }
};
template<bool Noexcept, typename T>
void test_noexcept_eq(T t)
{
std::indirect<T> i(t);
static_assert(noexcept(i == t) == Noexcept);
static_assert(noexcept(i != t) == Noexcept);
static_assert(noexcept(i == i) == Noexcept);
static_assert(noexcept(i != i) == Noexcept);
}
template<bool Noexcept, typename T>
void test_noexcept_rel(T t)
{
std::indirect<T> i(t);
static_assert(noexcept(i < t) == Noexcept);
static_assert(noexcept(i > t) == Noexcept);
static_assert(noexcept(i <= t) == Noexcept);
static_assert(noexcept(i >= t) == Noexcept);
static_assert(noexcept(i <=> t) == Noexcept);
static_assert(noexcept(t < i) == Noexcept);
static_assert(noexcept(t > i) == Noexcept);
static_assert(noexcept(t <= i) == Noexcept);
static_assert(noexcept(t >= i) == Noexcept);
static_assert(noexcept(t <=> i) == Noexcept);
static_assert(noexcept(i < i) == Noexcept);
static_assert(noexcept(i > i) == Noexcept);
static_assert(noexcept(i <= i) == Noexcept);
static_assert(noexcept(i >= i) == Noexcept);
static_assert(noexcept(i <=> i) == Noexcept);
}
void test_noexcept()
{
test_noexcept_eq<true>(Comp<true>());
test_noexcept_eq<false>(Comp<false>());
test_noexcept_rel<true>(Comp<true>());
test_noexcept_rel<false>(Comp<false>());
test_noexcept_eq<true>(Comp<true, BoolConv<true>>());
test_noexcept_eq<false>(Comp<true, BoolConv<false>>());
test_noexcept_eq<false>(Comp<false, BoolConv<true>>());
test_noexcept_eq<false>(Comp<false, BoolConv<false>>());
}
int main()
{
test_relops();
test_comp_with_t();
test_hash();
test_noexcept();
static_assert([] {
test_relops();
test_comp_with_t();
return true;
}());
}