blob: 57e089782d7f8e51715b968e5cdef416a2ed515f [file] [log] [blame]
#pragma once
#include <stdplus/concepts.hpp>
#include <concepts>
#include <type_traits>
#include <utility>
#include <variant>
namespace stdplus
{
namespace detail
{
template <template <typename, typename> typename Veq, typename...>
struct CanVeq;
template <template <typename, typename> typename Veq, typename T>
struct CanVeq<Veq, T>
{
static inline constexpr bool value = false;
};
template <template <typename, typename> typename Veq, typename T, typename V,
typename... Vs>
struct CanVeq<Veq, T, V, Vs...>
{
static inline constexpr bool value = Veq<T, V>::value ||
CanVeq<Veq, T, Vs...>::value;
};
template <typename T1, typename T2>
struct VeqBase
{
static inline constexpr bool value = false;
constexpr bool operator()(const T1&, const T2&) const noexcept
{
return false;
}
};
template <typename T1, typename T2>
struct VeqFuzzy : VeqBase<T1, T2>
{};
template <typename T1, WeaklyEqualityComparableWith<T1> T2>
struct VeqFuzzy<T1, T2>
{
static inline constexpr bool value = true;
constexpr bool operator()(const T1& lhs, const T2& rhs) const noexcept
{
return lhs == rhs;
}
};
template <typename T1, typename T2>
struct VeqStrict : VeqBase<T1, T2>
{};
template <typename T1, std::same_as<T1> T2>
struct VeqStrict<T1, T2>
{
static inline constexpr bool value = true;
constexpr bool operator()(const T1& lhs, const T2& rhs) const noexcept
{
return lhs == rhs;
}
};
} // namespace detail
template <template <typename, typename> 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 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