basedOpinionated utility library |
git clone git://git.dimitrijedobrota.com/based.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |
commit | 5c23715f617524c3b0e7c9273fde573ebfc7582e |
parent | a58fad2587466536fbbb95a9b054c5f1d25f594c |
author | Dimitrije Dobrota < mail@dimitrijedobrota.com > |
date | Mon, 5 May 2025 09:59:19 +0200 |
Enforce comaprison operation on enums
M | include/based/enum.hpp | | | +++++ |
M | include/based/type_traits.hpp | | | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --- |
M | test/source/enum_test.cpp | | | +++++++++++++ |
3 files changed, 84 insertions(+), 3 deletions(-)
diff --git a/ include/based/enum.hpp b/ include/based/enum.hpp
@@ -104,6 +104,11 @@
\
static const type& get(Type idx); \
\
friend bool operator==(type lhs, type rhs) \
{ \
return lhs.value == rhs.value; \
} \
\
Type value; \
}; \
\
diff --git a/ include/based/type_traits.hpp b/ include/based/type_traits.hpp
@@ -37,6 +37,9 @@
template<class T, class U> struct is_same : false_type { };
template<class T> struct is_same<T, T> : true_type { };
template<class T, class U> constexpr bool is_same_v = is_same<T, U>::value;
template<typename T, typename U>
concept SameAs = is_same_v<T, U> && is_same_v<U, T>;
template<class T> struct remove_reference { using type = T; };
template<class T> struct remove_reference<T&> { using type = T; };
template<class T> struct remove_reference<T&&> { using type = T; };
@@ -76,6 +79,69 @@
struct is_instantiable<T, void_t<T<Ts...>>, Ts...> : true_type {};
template<template<class...> class T, class... Ts>
inline constexpr auto is_instantiable_v = is_instantiable<T, void, Ts...>::value;
template<typename T>
concept equal_comparable = requires
(const remove_reference_t<T>& lhs, const remove_reference_t<T>& rhs)
{
{lhs == rhs} -> SameAs<bool>;
{rhs == lhs} -> SameAs<bool>;
};
template<typename T>
concept not_equal_comparable = requires
(const remove_reference_t<T>& lhs, const remove_reference_t<T>& rhs)
{
{lhs != rhs} -> SameAs<bool>;
{rhs != lhs} -> SameAs<bool>;
};
template<typename T>
concept less_comparable = requires
(const remove_reference_t<T>& lhs, const remove_reference_t<T>& rhs)
{
{lhs < rhs} -> SameAs<bool>;
{rhs < lhs} -> SameAs<bool>;
};
template<typename T>
concept greater_comparable = requires
(const remove_reference_t<T>& lhs, const remove_reference_t<T>& rhs)
{
{lhs > rhs} -> SameAs<bool>;
{rhs > lhs} -> SameAs<bool>;
};
template<typename T>
concept less_equal_comparable = requires
(const remove_reference_t<T>& lhs, const remove_reference_t<T>& rhs)
{
{lhs <= rhs} -> SameAs<bool>;
{rhs <= lhs} -> SameAs<bool>;
};
template<typename T>
concept greater_equal_comparable = requires
(const remove_reference_t<T>& lhs, const remove_reference_t<T>& rhs)
{
{lhs >= rhs} -> SameAs<bool>;
{rhs >= lhs} -> SameAs<bool>;
};
template<typename T>
concept equality_comparable = requires {
requires(equal_comparable<T>);
requires(not_equal_comparable<T>);
};
template<typename T>
concept totally_ordered = requires {
requires(equality_comparable<T>);
requires(less_comparable<T>);
requires(greater_comparable<T>);
requires(less_equal_comparable<T>);
requires(greater_equal_comparable<T>);
};
// clang-format on
/* ----- Integer ----- */
@@ -109,9 +175,6 @@
template<typename T>
concept BareRegular = std::regular<bare_t<T>>;
template<typename T, typename U>
concept SameAs = is_same_v<T, U> && is_same_v<U, T>;
template<typename T, typename U>
concept BareSameAs = SameAs<bare_t<T>, bare_t<U>>;
/* ----- Iterator ----- */
diff --git a/ test/source/enum_test.cpp b/ test/source/enum_test.cpp
@@ -4,6 +4,8 @@
#include <catch2/catch_test_macros.hpp>
#include "based/type_traits.hpp"
struct test
{
BASED_ENUM_DECLARE(var, std::uint8_t, a, b, c)
@@ -55,3 +57,14 @@
TEST_CASE("names", "[enum/enum]")
REQUIRE(std::strcmp(test::var::type::names[test::var::b], "b") == 0);
REQUIRE(std::strcmp(test::var::type::names[test::var::c], "c") == 0);
}
TEST_CASE("operations", "[enum/enum]")
{
using based::SameAs;
STATIC_REQUIRE(based::equality_comparable<test::var::type>);
STATIC_REQUIRE(!based::less_comparable<test::var::type>);
STATIC_REQUIRE(!based::greater_comparable<test::var::type>);
STATIC_REQUIRE(!based::less_equal_comparable<test::var::type>);
STATIC_REQUIRE(!based::greater_equal_comparable<test::var::type>);
}