blob: 61d2e27210760a547302b91c1d68bc481671bd6c [file] [log] [blame]
#include <type_traits>
#include <utility>
#include <variant>
namespace stdplus
{
namespace detail
{
template <template <typename, typename, typename = void> typename Veq,
typename...>
struct CanVeq;
template <template <typename, typename, typename = void> typename Veq,
typename T>
struct CanVeq<Veq, T>
{
static constexpr inline bool value = false;
};
template <template <typename, typename, typename = void> typename Veq,
typename T, typename V, typename... Vs>
struct CanVeq<Veq, T, V, Vs...>
{
static constexpr inline bool value = Veq<T, V>::value ||
CanVeq<Veq, T, Vs...>::value;
};
template <typename T1, typename T2>
struct VeqBase
{
static constexpr inline bool value = false;
constexpr bool operator()(const T1&, const T2&) const noexcept
{
return false;
}
};
template <typename T1, typename T2, typename = void>
struct VeqFuzzy : VeqBase<T1, T2>
{};
template <typename T1, typename T2>
struct VeqFuzzy<T1, T2,
std::enable_if_t<std::is_same_v<
decltype(std::declval<T1>() == std::declval<T2>()), bool>>>
{
static constexpr inline bool value = true;
constexpr bool operator()(const T1& lhs, const T2& rhs) const noexcept
{
return lhs == rhs;
}
};
template <typename T1, typename T2, typename = void>
struct VeqStrict : VeqBase<T1, T2>
{};
template <typename T1, typename T2>
struct VeqStrict<T1, T2, std::enable_if_t<std::is_same_v<T1, T2>>>
{
static constexpr inline bool value = true;
constexpr bool operator()(const T1& lhs, const T2& rhs) const noexcept
{
return lhs == rhs;
}
};
} // namespace detail
template <template <typename, typename, typename = void> typename Veq,
typename... Vs, typename T,
std::enable_if_t<detail::CanVeq<Veq, T, Vs...>::value, bool> = true>
constexpr bool variantEq(const std::variant<Vs...>& vs, const T& t) noexcept
{
return std::visit(
[&t](const auto& v) {
return Veq<std::remove_cvref_t<decltype(v)>, T>{}(v, t);
},
vs);
}
template <template <typename, typename, typename = void> typename Veq,
typename... Vs, typename... Vs2>
constexpr bool variantEq(const std::variant<Vs...>& vs,
const std::variant<Vs2...>& vs2) noexcept
{
return std::visit([&vs](const auto& v) { return variantEq<Veq>(vs, v); },
vs2);
}
template <typename... Vs>
constexpr bool variantEqFuzzy(const std::variant<Vs...>& vs,
const auto& t) noexcept
{
return variantEq<detail::VeqFuzzy>(vs, t);
}
template <typename... Vs>
constexpr bool variantEqStrict(const std::variant<Vs...>& vs,
const auto& t) noexcept
{
return variantEq<detail::VeqStrict>(vs, t);
}
} // namespace stdplus