Files
clice/include/Support/Compare.h
2025-02-05 14:10:11 +08:00

138 lines
3.2 KiB
C++

#pragma once
#include <vector>
#include "Enum.h"
#include "Struct.h"
namespace clice::refl {
template <typename LHS, typename RHS = LHS>
struct Equal {
constexpr static bool equal(const LHS& lhs, const RHS& rhs) {
return lhs == rhs;
}
};
struct equal_t {
template <typename LHS, typename RHS = LHS>
constexpr static bool operator() (const LHS& lhs, const RHS& rhs) {
return Equal<LHS, RHS>::equal(lhs, rhs);
}
};
constexpr inline equal_t equal;
template <typename T>
struct Equal<std::vector<T>> {
constexpr static bool equal(const std::vector<T>& lhs, const std::vector<T>& rhs) {
if(lhs.size() != rhs.size()) {
return false;
}
for(std::size_t i = 0; i < lhs.size(); ++i) {
if(!refl::equal(lhs[i], rhs[i])) {
return false;
}
}
return true;
}
};
template <reflectable_enum E>
struct Equal<E> {
constexpr static bool equal(E lhs, E rhs) {
return lhs.value() == rhs.value();
}
};
template <reflectable_struct T>
requires (!requires(T lhs, T rhs) {
{ lhs == rhs } -> std::convertible_to<bool>;
})
struct Equal<T> {
constexpr static bool equal(const T& lhs, const T& rhs) {
return foreach(lhs, rhs, [](const auto& lhs, const auto& rhs) {
return refl::equal(lhs, rhs);
});
}
};
template <typename RHS, typename LHS = RHS>
struct Less {
constexpr static bool less(const LHS& lhs, const RHS& rhs) {
return lhs < rhs;
}
};
struct less_t {
template <typename RHS, typename LHS = RHS>
constexpr static bool operator() (const LHS& lhs, const RHS& rhs) {
return Less<RHS, LHS>::less(lhs, rhs);
}
};
constexpr inline less_t less;
template <typename T>
struct Less<std::vector<T>> {
constexpr static bool less(const std::vector<T>& lhs, const std::vector<T>& rhs) {
if(lhs.size() != rhs.size()) {
return lhs.size() < rhs.size();
}
for(std::size_t i = 0; i < lhs.size(); ++i) {
if(refl::less(lhs[i], rhs[i])) {
return true;
}
}
return false;
}
};
template <reflectable_enum E>
struct Less<E> {
constexpr static bool less(E lhs, E rhs) {
return lhs.value() < rhs.value();
}
};
template <reflectable_struct T>
requires (!requires(T lhs, T rhs) {
{ lhs < rhs } -> std::convertible_to<bool>;
})
struct Less<T> {
constexpr static bool less(const T& lhs, const T& rhs) {
bool result = false;
foreach(lhs, rhs, [&](const auto& lhs, const auto& rhs) {
/// return false to break the loop.
if(refl::less(lhs, rhs)) {
result = true;
return false;
}
if(refl::less(rhs, lhs)) {
result = false;
return false;
}
/// continue the loop.
return true;
});
return result;
}
};
struct less_equal_t {
template <typename LHS, typename RHS = LHS>
constexpr static bool operator() (const LHS& lhs, const RHS& rhs) {
return equal(lhs, rhs) || less(lhs, rhs);
}
};
constexpr inline less_equal_t less_equal;
} // namespace clice::refl