blob: 4f1232598d60a5689e5116c71c1b76005c144551 [file] [log] [blame]
// { dg-do run { target c++26 } }
#include <type_traits>
#include <utility>
#include <testsuite_hooks.h>
namespace free_ops
{
template<int OpId>
struct UnaryOps
{
friend constexpr int
operator+(UnaryOps) noexcept requires (OpId == 0)
{ return OpId; }
friend constexpr int
operator-(UnaryOps) noexcept requires (OpId == 1)
{ return OpId; }
friend constexpr int
operator~(UnaryOps) noexcept requires (OpId == 2)
{ return OpId; }
friend constexpr int
operator!(UnaryOps) noexcept requires (OpId == 3)
{ return OpId; }
friend constexpr int
operator&(UnaryOps) noexcept requires (OpId == 4)
{ return OpId; }
friend constexpr int
operator*(UnaryOps) noexcept requires (OpId == 5)
{ return OpId; }
friend constexpr int
operator++(UnaryOps) noexcept requires (OpId == 6)
{ return OpId; }
friend constexpr int
operator++(UnaryOps, int) noexcept requires (OpId == 7)
{ return OpId; }
friend constexpr int
operator--(UnaryOps) noexcept requires (OpId == 8)
{ return OpId; }
friend constexpr int
operator--(UnaryOps, int) noexcept requires (OpId == 9)
{ return OpId; }
};
}
namespace member_ops
{
template<int OpId>
struct UnaryOps
{
constexpr int
operator+() const noexcept requires (OpId == 0)
{ return OpId; }
constexpr int
operator-() const noexcept requires (OpId == 1)
{ return OpId; }
constexpr int
operator~() const noexcept requires (OpId == 2)
{ return OpId; }
constexpr int
operator!() const noexcept requires (OpId == 3)
{ return OpId; }
constexpr int
operator&() const noexcept requires (OpId == 4)
{ return OpId; }
constexpr int
operator*() const noexcept requires (OpId == 5)
{ return OpId; }
constexpr int
operator++() const noexcept requires (OpId == 6)
{ return OpId; }
constexpr int
operator++(int) const noexcept requires (OpId == 7)
{ return OpId; }
constexpr int
operator--() const noexcept requires (OpId == 8)
{ return OpId; }
constexpr int
operator--(int) const noexcept requires (OpId == 9)
{ return OpId; }
};
}
constexpr size_t n_unary_ops = 10;
template<template<int> typename Ops, int OpId>
constexpr void
test_unary_operator()
{
auto x = std::cw<Ops<OpId>{}>;
auto check = [](auto c)
{
VERIFY(c == OpId);
static_assert(std::same_as<decltype(c), std::constant_wrapper<OpId>>);
};
if constexpr (OpId == 0)
check(+x);
if constexpr (OpId == 1)
check(-x);
if constexpr (OpId == 2)
check(~x);
if constexpr (OpId == 3)
check(!x);
if constexpr (OpId == 4)
check(&x);
if constexpr (OpId == 5)
check(*x);
if constexpr (OpId == 6)
check(++x);
if constexpr (OpId == 7)
check(x++);
if constexpr (OpId == 8)
check(--x);
if constexpr (OpId == 9)
check(x--);
static_assert(n_unary_ops == 10);
}
constexpr void
test_unary_operators_all()
{
auto run = []<size_t... Idx>(std::integer_sequence<size_t, Idx...>)
{
(test_unary_operator<free_ops::UnaryOps, Idx>(), ...);
(test_unary_operator<member_ops::UnaryOps, Idx>(), ...);
};
run(std::make_index_sequence<n_unary_ops>());
}
namespace free_ops
{
template<int OpId>
struct BinaryOps
{
friend constexpr int
operator+(BinaryOps, BinaryOps) noexcept requires (OpId == 0)
{ return OpId; }
friend constexpr int
operator-(BinaryOps, BinaryOps) noexcept requires (OpId == 1)
{ return OpId; }
friend constexpr int
operator*(BinaryOps, BinaryOps) noexcept requires (OpId == 2)
{ return OpId; }
friend constexpr int
operator/(BinaryOps, BinaryOps) noexcept requires (OpId == 3)
{ return OpId; }
friend constexpr int
operator%(BinaryOps, BinaryOps) noexcept requires (OpId == 4)
{ return OpId; }
friend constexpr int
operator<<(BinaryOps, BinaryOps) noexcept requires (OpId == 5)
{ return OpId; }
friend constexpr int
operator>>(BinaryOps, BinaryOps) noexcept requires (OpId == 6)
{ return OpId; }
friend constexpr int
operator&(BinaryOps, BinaryOps) noexcept requires (OpId == 7)
{ return OpId; }
friend constexpr int
operator|(BinaryOps, BinaryOps) noexcept requires (OpId == 8)
{ return OpId; }
friend constexpr int
operator^(BinaryOps, BinaryOps) noexcept requires (OpId == 9)
{ return OpId; }
friend constexpr int
operator&&(BinaryOps, BinaryOps) noexcept requires (OpId == 10)
{ return OpId; }
friend constexpr int
operator||(BinaryOps, BinaryOps) noexcept requires (OpId == 11)
{ return OpId; }
friend constexpr int
operator<=>(BinaryOps, BinaryOps) noexcept requires (OpId == 12)
{ return OpId; }
friend constexpr int
operator<(BinaryOps, BinaryOps) noexcept requires (OpId == 13)
{ return OpId; }
friend constexpr int
operator<=(BinaryOps, BinaryOps) noexcept requires (OpId == 14)
{ return OpId; }
friend constexpr int
operator==(BinaryOps, BinaryOps) noexcept requires (OpId == 15)
{ return OpId; }
friend constexpr int
operator!=(BinaryOps, BinaryOps) noexcept requires (OpId == 16)
{ return OpId; }
friend constexpr int
operator>(BinaryOps, BinaryOps) noexcept requires (OpId == 17)
{ return OpId; }
friend constexpr int
operator>=(BinaryOps, BinaryOps) noexcept requires (OpId == 18)
{ return OpId; }
friend constexpr int
operator+=(BinaryOps, BinaryOps) noexcept requires (OpId == 19)
{ return OpId; }
friend constexpr int
operator-=(BinaryOps, BinaryOps) noexcept requires (OpId == 20)
{ return OpId; }
friend constexpr int
operator*=(BinaryOps, BinaryOps) noexcept requires (OpId == 21)
{ return OpId; }
friend constexpr int
operator/=(BinaryOps, BinaryOps) noexcept requires (OpId == 22)
{ return OpId; }
friend constexpr int
operator%=(BinaryOps, BinaryOps) noexcept requires (OpId == 23)
{ return OpId; }
friend constexpr int
operator&=(BinaryOps, BinaryOps) noexcept requires (OpId == 24)
{ return OpId; }
friend constexpr int
operator|=(BinaryOps, BinaryOps) noexcept requires (OpId == 25)
{ return OpId; }
friend constexpr int
operator^=(BinaryOps, BinaryOps) noexcept requires (OpId == 26)
{ return OpId; }
friend constexpr int
operator<<=(BinaryOps, BinaryOps) noexcept requires (OpId == 27)
{ return OpId; }
friend constexpr int
operator>>=(BinaryOps, BinaryOps) noexcept requires (OpId == 28)
{ return OpId; }
};
}
namespace member_ops
{
template<int OpId>
struct BinaryOps
{
constexpr int
operator+(BinaryOps) const noexcept requires (OpId == 0)
{ return OpId; }
constexpr int
operator-(BinaryOps) const noexcept requires (OpId == 1)
{ return OpId; }
constexpr int
operator*(BinaryOps) const noexcept requires (OpId == 2)
{ return OpId; }
constexpr int
operator/(BinaryOps) const noexcept requires (OpId == 3)
{ return OpId; }
constexpr int
operator%(BinaryOps) const noexcept requires (OpId == 4)
{ return OpId; }
constexpr int
operator<<(BinaryOps) const noexcept requires (OpId == 5)
{ return OpId; }
constexpr int
operator>>(BinaryOps) const noexcept requires (OpId == 6)
{ return OpId; }
constexpr int
operator&(BinaryOps) const noexcept requires (OpId == 7)
{ return OpId; }
constexpr int
operator|(BinaryOps) const noexcept requires (OpId == 8)
{ return OpId; }
constexpr int
operator^(BinaryOps) const noexcept requires (OpId == 9)
{ return OpId; }
constexpr int
operator&&(BinaryOps) const noexcept requires (OpId == 10)
{ return OpId; }
constexpr int
operator||(BinaryOps) const noexcept requires (OpId == 11)
{ return OpId; }
constexpr int
operator<=>(BinaryOps) const noexcept requires (OpId == 12)
{ return OpId; }
constexpr int
operator<(BinaryOps) const noexcept requires (OpId == 13)
{ return OpId; }
constexpr int
operator<=(BinaryOps) const noexcept requires (OpId == 14)
{ return OpId; }
constexpr int
operator==(BinaryOps) const noexcept requires (OpId == 15)
{ return OpId; }
constexpr int
operator!=(BinaryOps) const noexcept requires (OpId == 16)
{ return OpId; }
constexpr int
operator>(BinaryOps) const noexcept requires (OpId == 17)
{ return OpId; }
constexpr int
operator>=(BinaryOps) const noexcept requires (OpId == 18)
{ return OpId; }
constexpr int
operator+=(BinaryOps) const noexcept requires (OpId == 19)
{ return OpId; }
constexpr int
operator-=(BinaryOps) const noexcept requires (OpId == 20)
{ return OpId; }
constexpr int
operator*=(BinaryOps) const noexcept requires (OpId == 21)
{ return OpId; }
constexpr int
operator/=(BinaryOps) const noexcept requires (OpId == 22)
{ return OpId; }
constexpr int
operator%=(BinaryOps) const noexcept requires (OpId == 23)
{ return OpId; }
constexpr int
operator&=(BinaryOps) const noexcept requires (OpId == 24)
{ return OpId; }
constexpr int
operator|=(BinaryOps) const noexcept requires (OpId == 25)
{ return OpId; }
constexpr int
operator^=(BinaryOps) const noexcept requires (OpId == 26)
{ return OpId; }
constexpr int
operator<<=(BinaryOps) const noexcept requires (OpId == 27)
{ return OpId; }
constexpr int
operator>>=(BinaryOps) const noexcept requires (OpId == 28)
{ return OpId; }
};
}
constexpr size_t n_binary_ops = 29;
template<template<int> typename Ops, int OpId>
constexpr void
test_binary_operator()
{
auto cx = std::cw<Ops<OpId>{}>;
auto cy = std::cw<Ops<OpId>{}>;
auto check = [](auto c)
{
VERIFY(c == OpId);
static_assert(std::same_as<decltype(c), std::constant_wrapper<OpId>>);
};
if constexpr (OpId == 0)
check(cx + cy);
if constexpr (OpId == 1)
check(cx - cy);
if constexpr (OpId == 2)
check(cx * cy);
if constexpr (OpId == 3)
check(cx / cy);
if constexpr (OpId == 4)
check(cx % cy);
if constexpr (OpId == 5)
check(cx << cy);
if constexpr (OpId == 6)
check(cx >> cy);
if constexpr (OpId == 7)
check(cx & cy);
if constexpr (OpId == 8)
check(cx | cy);
if constexpr (OpId == 10)
check(cx && cy);
if constexpr (OpId == 11)
check(cx || cy);
if constexpr (OpId == 12)
check(cx <=> cy);
if constexpr (OpId == 13)
check(cx < cy);
if constexpr (OpId == 14)
check(cx <= cy);
if constexpr (OpId == 15)
check(cx == cy);
if constexpr (OpId == 16)
check(cx != cy);
if constexpr (OpId == 17)
check(cx > cy);
if constexpr (OpId == 18)
check(cx >= cy);
if constexpr (OpId == 19)
check(cx += cy);
if constexpr (OpId == 20)
check(cx -= cy);
if constexpr (OpId == 21)
check(cx *= cy);
if constexpr (OpId == 22)
check(cx /= cy);
if constexpr (OpId == 23)
check(cx %= cy);
if constexpr (OpId == 24)
check(cx &= cy);
if constexpr (OpId == 25)
check(cx |= cy);
if constexpr (OpId == 26)
check(cx ^= cy);
if constexpr (OpId == 27)
check(cx <<= cy);
if constexpr (OpId == 28)
check(cx >>= cy);
static_assert(n_binary_ops == 29);
}
template<template<int> typename Ops, int OpId>
constexpr void
test_mixed_binary_operators()
{
constexpr auto x = Ops<OpId>{};
auto cx = std::cw<x>;
constexpr auto y = Ops<OpId>{};
auto cy = std::cw<y>;
auto check = [](auto vc, auto cv)
{
auto impl = [](auto c)
{
VERIFY(c == OpId);
static_assert(std::same_as<decltype(c), int>);
};
impl(vc);
impl(cv);
};
if constexpr (OpId == 0)
check(x + cy, cx + y);
if constexpr (OpId == 1)
check(x - cy, cx - y);
if constexpr (OpId == 2)
check(x * cy, cx * y);
if constexpr (OpId == 3)
check(x / cy, cx / y);
if constexpr (OpId == 4)
check(x % cy, cx % y);
if constexpr (OpId == 5)
check(x << cy, cx << y);
if constexpr (OpId == 6)
check(x >> cy, cx >> y);
if constexpr (OpId == 7)
check(x & cy, cx & y);
if constexpr (OpId == 8)
check(x | cy, cx | y);
if constexpr (OpId == 10)
check(x && cy, cx && y);
if constexpr (OpId == 11)
check(x || cy, cx || y);
if constexpr (OpId == 12)
check(x <=> cy, cx <=> y);
if constexpr (OpId == 13)
check(x < cy, cx < y);
if constexpr (OpId == 14)
check(x <= cy, cx <= y);
if constexpr (OpId == 15)
check(x == cy, cx == y);
if constexpr (OpId == 16)
check(x != cy, cx != y);
if constexpr (OpId == 17)
check(x > cy, cx > y);
if constexpr (OpId == 18)
check(x >= cy, cx >= y);
if constexpr (OpId == 19)
check(x += cy, cx += y);
if constexpr (OpId == 20)
check(x -= cy, cx -= y);
if constexpr (OpId == 21)
check(x *= cy, cx *= y);
if constexpr (OpId == 22)
check(x /= cy, cx /= y);
if constexpr (OpId == 23)
check(x %= cy, cx %= y);
if constexpr (OpId == 24)
check(x &= cy, cx &= y);
if constexpr (OpId == 25)
check(x |= cy, cx |= y);
if constexpr (OpId == 26)
check(x ^= cy, cx ^= y);
if constexpr (OpId == 27)
check(x <<= cy, cx <<= y);
if constexpr (OpId == 28)
check(x >>= cy, cx >>= y);
static_assert(n_binary_ops == 29);
}
constexpr void
test_binary_operators_all()
{
auto run = []<size_t... Idx>(std::integer_sequence<size_t, Idx...>)
{
(test_binary_operator<free_ops::BinaryOps, Idx>(), ...);
(test_mixed_binary_operators<free_ops::BinaryOps, Idx>(), ...);
(test_binary_operator<member_ops::BinaryOps, Idx>(), ...);
};
run(std::make_index_sequence<n_binary_ops>());
}
constexpr bool
test_all()
{
test_unary_operators_all();
test_binary_operators_all();
return true;
}
int
main()
{
test_all();
return 0;
}