basedOpinionated utility library |
git clone git://git.dimitrijedobrota.com/based.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |
commit | 60fb6e4800f2059f967fc494477beb52aa08199e |
parent | 01258c99d50a4507f526c66dc27984927ba05f7c |
author | Dimitrije Dobrota < mail@dimitrijedobrota.com > |
date | Sat, 10 May 2025 19:43:24 +0200 |
General cleanup, enums can start from any value
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, 75 insertions(+), 64 deletions(-)
diff --git a/ include/based/enum/enum.hpp b/ include/based/enum/enum.hpp
@@ -5,54 +5,57 @@
#include "based/macro/foreach.hpp"
#include "based/macro/foreach_1.hpp"
#include "based/macro/foreach_2.hpp"
#include "based/utility/forward.hpp"
// NOLINTBEGIN(*macro-usage*)
#define BASED_DETAIL_NUMARGS(...) (std::array {__VA_ARGS__}.size())
#define BASED_E_DETAIL_NUMARGS(...) (std::array {__VA_ARGS__}.size())
#define BASED_DETAIL_LIST_ELEM_STR(Name, Index) #Name,
#define BASED_E_DETAIL_LIST_ELEM_STR(Name, Index) #Name,
#define BASED_DETAIL_LIST_STR(...) \
BASED_FOREACH(BASED_DETAIL_LIST_ELEM_STR, __VA_ARGS__)
#define BASED_E_DETAIL_LIST_STR(...) \
BASED_FOREACH(BASED_E_DETAIL_LIST_ELEM_STR, __VA_ARGS__)
// NOLINTNEXTLINE(*macro-parentheses*)
#define BASED_DETAIL_SET(var, val) decltype(var) var = decltype(var) {val};
#define BASED_E_DETAIL_SET(var, val) decltype(var) var = decltype(var) {val};
#define BASED_DETAIL_DECLARE_ENUM_VAL(Name, Index) static const type Name;
#define BASED_E_DETAIL_DECLARE_VAL(Name, Index) static const type Name;
#define BASED_DETAIL_DECLARE_ENUM_CASE(Qualifier, Name, Index) \
#define BASED_E_DETAIL_DECLARE_CASE(Qualifier, Name, Index) \
case Qualifier::Name.value: \
return Name;
#define BASED_DETAIL_DEFINE_ENUM_VAL(Qualifier, Name, Index) \
inline constexpr BASED_DETAIL_SET( \
Qualifier::Name, Qualifier::type::size - (Index) - 1 \
#define BASED_E_DETAIL_DEFINE_VAL(Qualifier, Initial, Name, Index) \
inline constexpr BASED_E_DETAIL_SET( \
Qualifier::Name, (Initial) + Qualifier::type::size - (Index) - 1 \
)
#define BASED_DETAIL_DEFINE_ENUM_NAMES(Qualifier, ...) \
inline constexpr BASED_DETAIL_SET( \
Qualifier::type::names, BASED_DETAIL_LIST_STR(__VA_ARGS__) \
#define BASED_E_DETAIL_DEFINE_NAMES(Qualifier, ...) \
inline constexpr BASED_E_DETAIL_SET( \
Qualifier::type::names, BASED_E_DETAIL_LIST_STR(__VA_ARGS__) \
)
#define BASED_DETAIL_DEFINE_ENUM_GET(Qualifier, Type, ...) \
#define BASED_E_DETAIL_DEFINE_GET(Qualifier, Type, ...) \
inline const Qualifier::type& Qualifier::type::get(Type idx) \
{ \
/* NOLINTNEXTLINE(*paths-covered*) */ \
switch (idx) { \
BASED_FOREACH_1(Qualifier, BASED_DETAIL_DECLARE_ENUM_CASE, __VA_ARGS__) \
BASED_FOREACH_1(Qualifier, BASED_E_DETAIL_DECLARE_CASE, __VA_ARGS__) \
default: \
break; \
} \
assert(0); /* NOLINT(*assert*,cert-dcl03-c) */ \
}
#define BASED_DETAIL_DEFINE_ENUM(Qualifier, Type, ...) \
BASED_FOREACH_1(Qualifier, BASED_DETAIL_DEFINE_ENUM_VAL, __VA_ARGS__) \
BASED_DETAIL_DEFINE_ENUM_NAMES(Qualifier, __VA_ARGS__) \
BASED_DETAIL_DEFINE_ENUM_GET(Qualifier, Type, __VA_ARGS__)
#define BASED_E_DETAIL_DEFINE(Qualifier, Type, Initial, ...) \
BASED_FOREACH_2( \
Qualifier, Initial, BASED_E_DETAIL_DEFINE_VAL, __VA_ARGS__ \
) \
BASED_E_DETAIL_DEFINE_NAMES(Qualifier, __VA_ARGS__) \
BASED_E_DETAIL_DEFINE_GET(Qualifier, Type, __VA_ARGS__)
#define BASED_DECLARE_ENUM_ARRAY(Name) \
#define BASED_DECLARE_ARRAY(Name, Initial) \
template<typename T> \
class array : public std::array<T, Name::type::size> \
{ \
@@ -76,26 +79,26 @@
\
const T& operator[](Name::type val) const \
{ \
return base::operator[](val.value); \
return base::operator[](val.value - (Initial)); \
} \
\
T& operator[](Name::type val) \
{ \
return base::operator[](val.value); \
return base::operator[](val.value - (Initial)); \
} \
\
const T& at(Name::type val) const \
{ \
return base::operator[](val.value); \
return base::operator[](val.value - (Initial)); \
} \
\
T& at(Name::type val) \
{ \
return base::operator[](val.value); \
return base::operator[](val.value - (Initial)); \
} \
};
#define BASED_DECLARE_ENUM(Name, Type, ...) \
#define BASED_DECLARE_ENUM(Name, Type, Initial, ...) \
struct Name \
{ \
class type \
@@ -108,11 +111,13 @@
} \
\
public: \
using size_t = Type; \
static constexpr size_t size = \
BASED_DETAIL_NUMARGS(BASED_DETAIL_LIST_STR(__VA_ARGS__)); \
using value_type = Type; \
using size_type = Type; \
\
BASED_DECLARE_ENUM_ARRAY(Name) \
static constexpr size_type size = \
BASED_E_DETAIL_NUMARGS(BASED_E_DETAIL_LIST_STR(__VA_ARGS__)); \
\
BASED_DECLARE_ARRAY(Name, Initial) \
static const array<const char*> names; \
\
static const type& get(Type idx); \
@@ -125,13 +130,13 @@
Type value; \
}; \
\
BASED_FOREACH(BASED_DETAIL_DECLARE_ENUM_VAL, __VA_ARGS__) \
BASED_FOREACH(BASED_E_DETAIL_DECLARE_VAL, __VA_ARGS__) \
};
#define BASED_DEFINE_ENUM(Name, Type, ...) \
BASED_DETAIL_DEFINE_ENUM(Name, Type, __VA_ARGS__)
#define BASED_DEFINE_ENUM(Name, Type, Initial, ...) \
BASED_E_DETAIL_DEFINE(Name, Type, Initial, __VA_ARGS__)
#define BASED_DEFINE_ENUM_CLASS(Class, Name, Type, ...) \
BASED_DETAIL_DEFINE_ENUM(Class::Name, Type, __VA_ARGS__)
#define BASED_DEFINE_ENUM_CLASS(Class, Name, Type, Initial, ...) \
BASED_E_DETAIL_DEFINE(Class::Name, Type, Initial, __VA_ARGS__)
// NOLINTEND(*macro-usage*)
diff --git a/ include/based/enum/enum_flag.hpp b/ include/based/enum/enum_flag.hpp
@@ -7,48 +7,50 @@
// NOLINTBEGIN(*macro-usage*)
#define BASED_DETAIL_NUMARGS(...) (std::array {__VA_ARGS__}.size())
#define BASED_EF_DETAIL_NUMARGS(...) (std::array {__VA_ARGS__}.size())
#define BASED_DETAIL_LIST_ELEM_STR(Name, Index) #Name,
#define BASED_EF_DETAIL_LIST_ELEM_STR(Name, Index) #Name,
#define BASED_DETAIL_LIST_STR(...) \
BASED_FOREACH(BASED_DETAIL_LIST_ELEM_STR, __VA_ARGS__)
#define BASED_EF_DETAIL_LIST_STR(...) \
BASED_FOREACH(BASED_EF_DETAIL_LIST_ELEM_STR, __VA_ARGS__)
// NOLINTNEXTLINE(*macro-parentheses*)
#define BASED_DETAIL_SET(var, val) decltype(var) var = decltype(var) {val};
#define BASED_EF_DETAIL_SET(var, val) decltype(var) var = decltype(var) {val};
#define BASED_DETAIL_DECLARE_ENUM_VAL(Name, Index) static const type Name;
#define BASED_EF_DETAIL_DECLARE_ENUM_VAL(Name, Index) static const type Name;
#define BASED_DETAIL_DECLARE_ENUM_CASE(Qualifier, Name, Index) \
#define BASED_EF_DETAIL_DECLARE_ENUM_CASE(Qualifier, Name, Index) \
case Qualifier::Name.value: \
return Name;
#define BASED_DETAIL_DEFINE_ENUM_FLAG_VAL(Qualifier, Name, Index) \
inline constexpr BASED_DETAIL_SET( \
#define BASED_EF_DETAIL_DEFINE_VAL(Qualifier, Name, Index) \
inline constexpr BASED_EF_DETAIL_SET( \
Qualifier::Name, \
Qualifier::type::size_t {1} \
<< Qualifier::type::size_t {Qualifier::type::size - (Index) - 2} \
Qualifier::type::value_type {1} \
<< Qualifier::type::value_type {Qualifier::type::size - (Index) - 2} \
)
#define BASED_DETAIL_DEFINE_ENUM_FLAG_VALS(Qualifier, First, ...) \
BASED_FOREACH_1(Qualifier, BASED_DETAIL_DEFINE_ENUM_FLAG_VAL, __VA_ARGS__) \
inline constexpr BASED_DETAIL_SET(Qualifier::First, 0)
#define BASED_EF_DETAIL_DEFINE_VALS(Qualifier, First, ...) \
BASED_FOREACH_1(Qualifier, BASED_EF_DETAIL_DEFINE_VAL, __VA_ARGS__) \
inline constexpr BASED_EF_DETAIL_SET(Qualifier::First, 0)
#define BASED_DETAIL_DEFINE_ENUM_GET(Qualifier, Type, ...) \
#define BASED_EF_DETAIL_DEFINE_GET(Qualifier, Type, ...) \
inline const Qualifier::type& Qualifier::type::get(Type idx) \
{ \
/* NOLINTNEXTLINE(*paths-covered*) */ \
switch (idx) { \
BASED_FOREACH_1(Qualifier, BASED_DETAIL_DECLARE_ENUM_CASE, __VA_ARGS__) \
BASED_FOREACH_1( \
Qualifier, BASED_EF_DETAIL_DECLARE_ENUM_CASE, __VA_ARGS__ \
) \
default: \
break; \
} \
assert(0); /* NOLINT(*assert*,cert-dcl03-c) */ \
}
#define BASED_DETAIL_DEFINE_ENUM(Qualifier, Type, ...) \
BASED_DETAIL_DEFINE_ENUM_FLAG_VALS(Qualifier, __VA_ARGS__) \
BASED_DETAIL_DEFINE_ENUM_GET(Qualifier, Type, __VA_ARGS__)
#define BASED_EF_DETAIL_DEFINE(Qualifier, Type, ...) \
BASED_EF_DETAIL_DEFINE_VALS(Qualifier, __VA_ARGS__) \
BASED_EF_DETAIL_DEFINE_GET(Qualifier, Type, __VA_ARGS__)
#define BASED_DECLARE_ENUM_FLAG(Name, Type, ...) \
struct Name \
@@ -63,9 +65,11 @@
} \
\
public: \
using size_t = Type; \
static constexpr size_t size = \
BASED_DETAIL_NUMARGS(BASED_DETAIL_LIST_STR(__VA_ARGS__)); \
using value_type = Type; \
using size_type = Type; \
\
static constexpr size_type size = \
BASED_EF_DETAIL_NUMARGS(BASED_EF_DETAIL_LIST_STR(__VA_ARGS__)); \
\
static const type& get(Type idx); \
\
@@ -145,13 +149,13 @@
Type value; \
}; \
\
BASED_FOREACH(BASED_DETAIL_DECLARE_ENUM_VAL, __VA_ARGS__) \
BASED_FOREACH(BASED_EF_DETAIL_DECLARE_ENUM_VAL, __VA_ARGS__) \
};
#define BASED_DEFINE_ENUM_FLAG(Name, Type, ...) \
BASED_DETAIL_DEFINE_ENUM(Name, Type, __VA_ARGS__)
BASED_EF_DETAIL_DEFINE(Name, Type, __VA_ARGS__)
#define BASED_DEFINE_ENUM_FLAG_CLASS(Class, Name, Type, ...) \
BASED_DETAIL_DEFINE_ENUM(Class::Name, Type, __VA_ARGS__)
BASED_EF_DETAIL_DEFINE(Class::Name, Type, __VA_ARGS__)
// NOLINTEND(*macro-usage*)
diff --git a/ include/based/instrumentation/instrumented.hpp b/ include/based/instrumentation/instrumented.hpp
@@ -20,6 +20,7 @@
struct instrumented_base
BASED_DECLARE_ENUM(
op,
u8,
0,
n,
ctor_default,
ctor_value,
@@ -45,6 +46,7 @@
BASED_DEFINE_ENUM_CLASS(
instrumented_base,
op,
u8,
0,
n,
ctor_default,
ctor_value,
@@ -198,7 +200,7 @@
void count_operations(
)
{
using instrumented = instrumented<double>;
using esize_t = instrumented::op::type::size_t;
using esize_t = instrumented::op::type::size_type;
constexpr esize_t cols = instrumented::op::type::size;
const esize_t decimals((norm == dont_normalize) ? 0 : 2);
diff --git a/ test/source/enum_flag_test.cpp b/ test/source/enum_flag_test.cpp
@@ -15,7 +15,7 @@
BASED_DECLARE_ENUM_FLAG(var, based::u8, empty, a, b, c)
BASED_DEFINE_ENUM_FLAG(var, based::u8, empty, a, b, c)
TEST_CASE("types", "[enum/enum]")
TEST_CASE("types", "[enum/enum_flag]")
{
STATIC_REQUIRE(requires { typename var; });
STATIC_REQUIRE(requires { var::empty; });
@@ -29,7 +29,7 @@
TEST_CASE("types", "[enum/enum]")
STATIC_REQUIRE(var::c.value == 4);
}
TEST_CASE("operations", "[enum/enum]")
TEST_CASE("operations", "[enum/enum_flag]")
{
using based::SameAs;
diff --git a/ test/source/enum_test.cpp b/ test/source/enum_test.cpp
@@ -15,7 +15,7 @@
struct test
{
BASED_DECLARE_ENUM(var, based::u8, a, b, c)
BASED_DECLARE_ENUM(var, based::u8, 0, a, b, c)
[[nodiscard]] int get_var(var::type req) const;
@@ -25,7 +25,7 @@
private:
int m_c = 3;
};
BASED_DEFINE_ENUM_CLASS(test, var, based::u8, a, b, c)
BASED_DEFINE_ENUM_CLASS(test, var, based::u8, 0, a, b, c)
inline int test::get_var(var::type req) const
{