basedOpinionated utility library |
git clone git://git.dimitrijedobrota.com/based.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |
commit | 91b7f9f59b567fcb3c11872e0fc7dec0fef2da13 |
parent | e0ae95c6466e73a9afcaffc16d1ab757e39525f7 |
author | Dimitrije Dobrota < mail@dimitrijedobrota.com > |
date | Tue, 20 May 2025 21:48:16 +0200 |
Enum cleanup
M | include/based/enum/enum.hpp | | | ++++++++++++++++++++++++++ -------------------- |
M | include/based/enum/enum_flag.hpp | | | +++++++++++++++++++++++++++ -------------------------- |
M | include/based/instrumentation/instrumented.hpp | | | +++++++++ --------- |
M | test/source/enum_flag_test.cpp | | | +++++++ ------- |
M | test/source/enum_test.cpp | | | ++++++++++++++++++ ------------------ |
5 files changed, 87 insertions(+), 80 deletions(-)
diff --git a/ include/based/enum/enum.hpp b/ include/based/enum/enum.hpp
@@ -20,7 +20,7 @@
// NOLINTNEXTLINE(*macro-parentheses*)
#define BASED_E_DETAIL_SET(var, val) decltype(var) var = decltype(var) {val};
#define BASED_E_DETAIL_DECLARE_VAL(Name, Index) static const type Name;
#define BASED_E_DETAIL_DECLARE_VAL(Name, Index) static const enum_type Name;
#define BASED_E_DETAIL_DECLARE_CASE(Qualifier, Name, Index) \
case Qualifier::Name.value: \
@@ -29,17 +29,17 @@
#define BASED_E_DETAIL_DEFINE_VAL(Qualifier, Initial, Name, Index) \
inline constexpr BASED_E_DETAIL_SET( \
Qualifier::Name, \
Qualifier::type::value_type {Initial} + Qualifier::type::size - (Index) \
- 1 \
Qualifier::enum_type::value_type {Initial} + Qualifier::enum_type::size \
- (Index) - 1 \
)
#define BASED_E_DETAIL_DEFINE_NAMES(Qualifier, ...) \
inline constexpr BASED_E_DETAIL_SET( \
Qualifier::type::names, BASED_E_DETAIL_LIST_STR(__VA_ARGS__) \
Qualifier::enum_type::names, BASED_E_DETAIL_LIST_STR(__VA_ARGS__) \
)
#define BASED_E_DETAIL_DEFINE_GET(Qualifier, Type, ...) \
inline const Qualifier::type& Qualifier::type::get(Type idx) \
inline const Qualifier::enum_type& Qualifier::enum_type::get(Type idx) \
{ \
/* NOLINTNEXTLINE(*paths-covered*) */ \
switch (idx) { \
@@ -57,9 +57,10 @@
#define BASED_DECLARE_ARRAY(Name, Initial) \
template<typename T> \
class array : public std::array<T, Name::type::size> \
class array : public std::array<T, Name::enum_type::size> \
{ \
using base = std::array<T, Name::type::size>; \
using enum_type = Name::enum_type; \
using base = std::array<T, enum_type::size>; \
using base::operator[]; \
using base::at; \
\
@@ -70,42 +71,42 @@
} \
\
template<class... Args> \
requires(Name::type::size_type(sizeof...(Args)) == Name::type::size) \
requires(enum_type::size_type(sizeof...(Args)) == enum_type::size) \
constexpr explicit array(Args&&... args \
) noexcept /* NOLINTNEXTLINE(*decay*) */ \
: base({based::forward<Args>(args)...}) \
{ \
} \
\
const T& operator[](Name::type val) const \
const T& operator[](enum_type val) const \
{ \
return base::operator[](val.value - Name::type::value_type {Initial}); \
return base::operator[](val.value - enum_type::value_type {Initial}); \
} \
\
T& operator[](Name::type val) \
T& operator[](enum_type val) \
{ \
return base::operator[](val.value - Name::type::value_type {Initial}); \
return base::operator[](val.value - enum_type::value_type {Initial}); \
} \
\
const T& at(Name::type val) const \
const T& at(enum_type val) const \
{ \
return base::operator[](val.value - Name::type::value_type {Initial}); \
return base::operator[](val.value - enum_type::value_type {Initial}); \
} \
\
T& at(Name::type val) \
T& at(enum_type val) \
{ \
return base::operator[](val.value - Name::type::value_type {Initial}); \
return base::operator[](val.value - enum_type::value_type {Initial}); \
} \
};
#define BASED_DECLARE_ENUM(Name, Type, Initial, ...) \
struct Name \
{ \
class type \
class enum_type \
{ \
friend Name; \
\
constexpr explicit type(Type enum_value) \
constexpr explicit enum_type(Type enum_value) \
: value(enum_value) \
{ \
} \
@@ -120,9 +121,14 @@
BASED_DECLARE_ARRAY(Name, Initial) \
static const array<const char*> names; \
\
static const type& get(Type idx); \
static const enum_type& get(Type idx); \
\
friend bool operator==(type lhs, type rhs) \
constexpr Type operator()() const \
{ \
return value; \
} \
\
friend bool operator==(enum_type lhs, enum_type rhs) \
{ \
return lhs.value == rhs.value; \
} \
diff --git a/ include/based/enum/enum_flag.hpp b/ include/based/enum/enum_flag.hpp
@@ -17,7 +17,8 @@
// NOLINTNEXTLINE(*macro-parentheses*)
#define BASED_EF_DETAIL_SET(var, val) decltype(var) var = decltype(var) {val};
#define BASED_EF_DETAIL_DECLARE_ENUM_VAL(Name, Index) static const type Name;
#define BASED_EF_DETAIL_DECLARE_ENUM_VAL(Name, Index) \
static const enum_type Name;
#define BASED_EF_DETAIL_DECLARE_ENUM_CASE(Qualifier, Name, Index) \
case Qualifier::Name.value: \
@@ -26,8 +27,8 @@
#define BASED_EF_DETAIL_DEFINE_VAL(Qualifier, Name, Index) \
inline constexpr BASED_EF_DETAIL_SET( \
Qualifier::Name, \
Qualifier::type::value_type {1} \
<< Qualifier::type::value_type {Qualifier::type::size - (Index) - 2} \
Qualifier::enum_type::value_type {1} << Qualifier::enum_type:: \
value_type {Qualifier::enum_type::size - (Index) - 2} \
)
#define BASED_EF_DETAIL_DEFINE_VALS(Qualifier, First, ...) \
@@ -35,7 +36,7 @@
inline constexpr BASED_EF_DETAIL_SET(Qualifier::First, 0)
#define BASED_EF_DETAIL_DEFINE_GET(Qualifier, Type, ...) \
inline const Qualifier::type& Qualifier::type::get(Type idx) \
inline const Qualifier::enum_type& Qualifier::enum_type::get(Type idx) \
{ \
/* NOLINTNEXTLINE(*paths-covered*) */ \
switch (idx) { \
@@ -55,12 +56,12 @@
#define BASED_DECLARE_ENUM_FLAG(Name, Type, ...) \
struct Name \
{ \
class type \
class enum_type \
{ \
friend Name; \
friend struct based::enum_flag_wrapper<type>; \
friend struct based::enum_flag_wrapper<enum_type>; \
\
constexpr explicit type(Type enum_value) \
constexpr explicit enum_type(Type enum_value) \
: value(enum_value) \
{ \
} \
@@ -72,76 +73,76 @@
static constexpr size_type size = \
BASED_EF_DETAIL_NUMARGS(BASED_EF_DETAIL_LIST_STR(__VA_ARGS__)); \
\
static const type& get(Type idx); \
static const enum_type& get(Type idx); \
\
type& set(type val) \
enum_type& set(enum_type val) \
{ \
return *this |= val; \
} \
\
type& mask(type val) \
enum_type& mask(enum_type val) \
{ \
return *this &= val; \
} \
\
type& tgl(type val) \
enum_type& tgl(enum_type val) \
{ \
return *this ^= val; \
} \
\
type& neg() \
enum_type& neg() \
{ \
return *this = ~*this; \
} \
\
type& clear(type val) \
enum_type& clear(enum_type val) \
{ \
return *this &= ~val; \
} \
\
bool test(type val) const \
bool test(enum_type val) const \
{ \
return (*this & val) == val; \
} \
\
friend bool operator==(type lhs, type rhs) \
friend bool operator==(enum_type lhs, enum_type rhs) \
{ \
return lhs.value == rhs.value; \
} \
\
friend type operator|(type lhs, type rhs) \
friend enum_type operator|(enum_type lhs, enum_type rhs) \
{ \
return type(lhs.value | rhs.value); \
return enum_type(lhs.value | rhs.value); \
} \
\
friend type operator&(type lhs, type rhs) \
friend enum_type operator&(enum_type lhs, enum_type rhs) \
{ \
return type(lhs.value & rhs.value); \
return enum_type(lhs.value & rhs.value); \
} \
\
friend type operator^(type lhs, type rhs) \
friend enum_type operator^(enum_type lhs, enum_type rhs) \
{ \
return type(lhs.value ^ rhs.value); \
return enum_type(lhs.value ^ rhs.value); \
} \
\
type operator~() const \
enum_type operator~() const \
{ \
return type(~value); \
return enum_type(~value); \
} \
\
type& operator|=(type rhs) \
enum_type& operator|=(enum_type rhs) \
{ \
value |= rhs.value; \
return *this; \
} \
\
type& operator&=(type rhs) \
enum_type& operator&=(enum_type rhs) \
{ \
value &= rhs.value; \
return *this; \
} \
\
type& operator^=(type rhs) \
enum_type& operator^=(enum_type rhs) \
{ \
value ^= rhs.value; \
return *this; \
diff --git a/ include/based/instrumentation/instrumented.hpp b/ include/based/instrumentation/instrumented.hpp
@@ -19,7 +19,7 @@
struct instrumented_base
{
BASED_DECLARE_ENUM(
op,
u8,
based::bu8,
0,
n,
ctor_default,
@@ -33,7 +33,7 @@
struct instrumented_base
comparison
)
static op::type::array<double> counts;
static op::enum_type::array<double> counts;
static void initialize(size_t size)
{
@@ -45,7 +45,7 @@
struct instrumented_base
BASED_DEFINE_ENUM_CLASS(
instrumented_base,
op,
u8,
bu8,
0,
n,
ctor_default,
@@ -200,18 +200,18 @@
void count_operations(
)
{
using instrumented = instrumented<double>;
using esize_t = instrumented::op::type::size_type;
using esize_t = instrumented::op::enum_type::size_type;
constexpr esize_t cols = instrumented::op::type::size;
constexpr esize_t cols = instrumented::op::enum_type::size;
const esize_t decimals((norm == dont_normalize) ? 0 : 2);
instrumented_base::op::type::array<double> values;
instrumented_base::op::enum_type::array<double> values;
static constexpr int width = 12;
table tbl(width);
tbl.print_header(
std::begin(instrumented::op::type::names),
std::end(instrumented::op::type::names)
std::begin(instrumented::op::enum_type::names),
std::end(instrumented::op::enum_type::names)
);
std::mt19937 rng(0); // NOLINT(*cert-msc32-c*, *cert-msc51-cpp*)
@@ -227,7 +227,7 @@
void count_operations(
values[instrumented_base::op::n] = dbl;
for (esize_t k = 1; k < cols; ++k) {
const auto& val = instrumented::op::type::get(k);
const auto& val = instrumented::op::enum_type::get(k);
values[val] = norm(instrumented::counts[val], dbl);
}
diff --git a/ test/source/enum_flag_test.cpp b/ test/source/enum_flag_test.cpp
@@ -22,7 +22,7 @@
TEST_CASE("types", "[enum/enum_flag]")
STATIC_REQUIRE(requires { var::a; });
STATIC_REQUIRE(requires { var::b; });
STATIC_REQUIRE(requires { var::c; });
STATIC_REQUIRE(var::type::size == 4);
STATIC_REQUIRE(var::enum_type::size == 4);
STATIC_REQUIRE(var::empty.value == 0);
STATIC_REQUIRE(var::a.value == 1);
STATIC_REQUIRE(var::b.value == 2);
@@ -35,11 +35,11 @@
TEST_CASE("operations", "[enum/enum_flag]")
SECTION("COMPARE")
{
STATIC_REQUIRE(based::EqualityComparable<var::type>);
STATIC_REQUIRE(!based::LessComparable<var::type>);
STATIC_REQUIRE(!based::GreaterComparable<var::type>);
STATIC_REQUIRE(!based::LessEqualComparable<var::type>);
STATIC_REQUIRE(!based::GreaterEqualComparable<var::type>);
STATIC_REQUIRE(based::EqualityComparable<var::enum_type>);
STATIC_REQUIRE(!based::LessComparable<var::enum_type>);
STATIC_REQUIRE(!based::GreaterComparable<var::enum_type>);
STATIC_REQUIRE(!based::LessEqualComparable<var::enum_type>);
STATIC_REQUIRE(!based::GreaterEqualComparable<var::enum_type>);
}
SECTION("functions")
@@ -75,7 +75,7 @@
TEST_CASE("enum_flag_wrapper", "[enum/enum_flag_wrapper]")
based::bu8 flags = 0;
{
auto wrapper = based::enum_flag_wrapper<var::type>(flags);
auto wrapper = based::enum_flag_wrapper<var::enum_type>(flags);
wrapper |= var::a;
wrapper |= var::c;
diff --git a/ test/source/enum_test.cpp b/ test/source/enum_test.cpp
@@ -17,7 +17,7 @@
struct test
{
BASED_DECLARE_ENUM(var, based::bu8, 0, a, b, c)
[[nodiscard]] int get_var(var::type req) const;
[[nodiscard]] int get_var(var::enum_type req) const;
private:
int m_a = 1;
@@ -27,14 +27,14 @@
private:
BASED_DEFINE_ENUM_CLASS(test, var, based::bu8, 0, a, b, c)
inline int test::get_var(var::type req) const
inline int test::get_var(var::enum_type req) const
{
switch (req.value) {
case var::a.value:
switch (req()) {
case var::a():
return m_a;
case var::b.value:
case var::b():
return m_b;
case var::c.value:
case var::c():
return m_c;
default:
return -1;
@@ -47,10 +47,10 @@
TEST_CASE("types", "[enum/enum]")
STATIC_REQUIRE(requires { test::var::a; });
STATIC_REQUIRE(requires { test::var::b; });
STATIC_REQUIRE(requires { test::var::c; });
STATIC_REQUIRE(test::var::type::size == 3);
STATIC_REQUIRE(test::var::a.value == 0);
STATIC_REQUIRE(test::var::b.value == 1);
STATIC_REQUIRE(test::var::c.value == 2);
STATIC_REQUIRE(test::var::enum_type::size == 3);
STATIC_REQUIRE(test::var::a() == 0);
STATIC_REQUIRE(test::var::b() == 1);
STATIC_REQUIRE(test::var::c() == 2);
}
TEST_CASE("safety", "[enum/enum]")
@@ -67,18 +67,18 @@
TEST_CASE("safety", "[enum/enum]")
TEST_CASE("names", "[enum/enum]")
{
REQUIRE(std::strcmp(test::var::type::names[test::var::a], "a") == 0);
REQUIRE(std::strcmp(test::var::type::names[test::var::b], "b") == 0);
REQUIRE(std::strcmp(test::var::type::names[test::var::c], "c") == 0);
REQUIRE(std::strcmp(test::var::enum_type::names[test::var::a], "a") == 0);
REQUIRE(std::strcmp(test::var::enum_type::names[test::var::b], "b") == 0);
REQUIRE(std::strcmp(test::var::enum_type::names[test::var::c], "c") == 0);
}
TEST_CASE("operations", "[enum/enum]")
{
using based::SameAs;
STATIC_REQUIRE(based::EqualityComparable<test::var::type>);
STATIC_REQUIRE(!based::LessComparable<test::var::type>);
STATIC_REQUIRE(!based::GreaterComparable<test::var::type>);
STATIC_REQUIRE(!based::LessEqualComparable<test::var::type>);
STATIC_REQUIRE(!based::GreaterEqualComparable<test::var::type>);
STATIC_REQUIRE(based::EqualityComparable<test::var::enum_type>);
STATIC_REQUIRE(!based::LessComparable<test::var::enum_type>);
STATIC_REQUIRE(!based::GreaterComparable<test::var::enum_type>);
STATIC_REQUIRE(!based::LessEqualComparable<test::var::enum_type>);
STATIC_REQUIRE(!based::GreaterEqualComparable<test::var::enum_type>);
}