Skip to content

Commit 02d8535

Browse files
Began developing enums
1 parent 5e6489a commit 02d8535

9 files changed

Lines changed: 193 additions & 128 deletions

File tree

‎include/rfl/enums.hpp‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "Result.hpp"
88
#include "internal/enums/get_enum_names.hpp"
9+
#include "internal/enums/is_flag_enum.hpp"
910
#include "internal/strings/strings.hpp"
1011
#include "thirdparty/enchantum/bitflags.hpp"
1112
#include "thirdparty/enchantum/enchantum.hpp"
@@ -61,7 +62,7 @@ std::string enum_to_string(const EnumType _enum) {
6162
: std::string(s);
6263
};
6364

64-
if constexpr (enchantum::is_bitflag<EnumType>) {
65+
if constexpr (internal::enums::is_flag_enum<EnumType>) {
6566
// Iterates through the enum bit by bit and matches it against the flags.
6667
using T = std::underlying_type_t<EnumType>;
6768
auto val = static_cast<T>(_enum);
@@ -110,7 +111,7 @@ Result<EnumType> string_to_enum(const std::string& _str) {
110111
}
111112
};
112113

113-
if constexpr (enchantum::is_bitflag<EnumType>) {
114+
if constexpr (internal::enums::is_flag_enum<EnumType>) {
114115
using T = std::underlying_type_t<EnumType>;
115116
const auto split = internal::strings::split(_str, "|");
116117
auto res = static_cast<T>(0);

‎include/rfl/internal/StringLiteral.hpp‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
#include <string>
88
#include <string_view>
99

10-
namespace rfl {
11-
namespace internal {
10+
namespace rfl::internal {
1211

1312
/// Normal strings cannot be used as template
1413
/// parameters, but this can. This is needed
@@ -65,7 +64,6 @@ constexpr inline bool operator!=(const StringLiteral<N1>& _first,
6564
return !(_first == _second);
6665
}
6766

68-
} // namespace internal
69-
} // namespace rfl
67+
} // namespace rfl::internal
7068

7169
#endif

‎include/rfl/internal/enums/Names.hpp‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@
77
#include <utility>
88

99
#include "../../Literal.hpp"
10-
//#include "../../config.hpp"
11-
//#include "../../define_literal.hpp"
1210
#include "../../make_named_tuple.hpp"
13-
//#include "../../thirdparty/enchantum/enchantum.hpp"
1411
#include "../StringLiteral.hpp"
1512

1613
namespace rfl::internal::enums {
@@ -66,4 +63,3 @@ names_to_underlying_enumerator_array(
6663
} // namespace rfl::internal::enums
6764

6865
#endif
69-
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#ifndef RFL_INTERNAL_ENUMS_CPP20_GET_ENUM_NAMES_HPP_
2+
#define RFL_INTERNAL_ENUMS_CPP20_GET_ENUM_NAMES_HPP_
3+
4+
// Enum values must be greater than or equal to RFL_ENUM_RANGE_MIN.
5+
// By default, RFL_ENUM_RANGE_MIN is set to -256.
6+
// To change the default minimum range for all enum types, redefine the macro
7+
// RFL_ENUM_RANGE_MIN.
8+
#if !defined(RFL_ENUM_RANGE_MIN)
9+
#define RFL_ENUM_RANGE_MIN -256
10+
#endif
11+
12+
// Enum values must be less than or equal to RFL_ENUM_RANGE_MAX.
13+
// By default, RFL_ENUM_RANGE_MAX is set to 256.
14+
// To change the default maximum range for all enum types, redefine the macro
15+
// RFL_ENUM_RANGE_MAX.
16+
#if !defined(RFL_ENUM_RANGE_MAX)
17+
#define RFL_ENUM_RANGE_MAX 256
18+
#endif
19+
20+
#ifdef ENCHANTUM_MIN_RANGE
21+
#undef ENCHANTUM_MIN_RANGE
22+
#endif
23+
#define ENCHANTUM_MIN_RANGE RFL_ENUM_RANGE_MIN
24+
25+
#ifdef ENCHANTUM_MAX_RANGE
26+
#undef ENCHANTUM_MAX_RANGE
27+
#endif
28+
#define ENCHANTUM_MAX_RANGE RFL_ENUM_RANGE_MAX
29+
30+
#include <concepts>
31+
#include <utility>
32+
33+
#include "../../../Literal.hpp"
34+
#include "../../../thirdparty/enchantum/enchantum.hpp" // NOLINT(unused-includes)
35+
#include "../Names.hpp"
36+
#include "../is_flag_enum.hpp"
37+
#include "range_defined.hpp"
38+
39+
// https://en.cppreference.com/w/cpp/language/static_cast:
40+
41+
// 8) A value of integer or enumeration type can be converted to any complete
42+
// enumeration type.
43+
44+
// If the underlying type is not fixed, the behavior is undefined if the value
45+
// of expression is out of range (the range is all values possible for the
46+
// smallest bit-field large enough to hold all enumerators of the target
47+
// enumeration). If the underlying type is fixed, the result is the same as
48+
// converting the original value first to the underlying type of the enumeration
49+
// and then to the enumeration type.
50+
51+
// https://en.cppreference.com/w/cpp/language/enum
52+
53+
// enum struct|class name { enumerator = constexpr , enumerator = constexpr ,
54+
// ... } (1)
55+
// ...
56+
// 1) declares a scoped enumeration type whose underlying type is int (the
57+
// keywords class and struct are exactly equivalent)
58+
//
59+
// --> These rules taken together imply that if you EITHER fix the type OR you
60+
// use a scoped integer, static_cast<MyEnum>(some_integer_value) will always be
61+
// defined.
62+
63+
template <enchantum::Enum E>
64+
requires requires(E e) {
65+
{ e | e } -> std::same_as<E>;
66+
}
67+
constexpr inline bool enchantum::is_bitflag<E> = true;
68+
69+
// Specialize the enchantum EnumTraits further, so rfl::config::enum_range
70+
// works.
71+
namespace enchantum {
72+
73+
template <SignedEnum E>
74+
requires rfl::internal::enums::range_defined<E>
75+
struct enum_traits<E> {
76+
static constexpr std::size_t prefix_length = 0;
77+
78+
static constexpr auto min = rfl::config::enum_range<E>::min;
79+
static constexpr auto max = rfl::config::enum_range<E>::max;
80+
};
81+
82+
template <UnsignedEnum E>
83+
requires rfl::internal::enums::range_defined<E>
84+
struct enum_traits<E> {
85+
static constexpr std::size_t prefix_length = 0;
86+
87+
static constexpr auto min = rfl::config::enum_range<E>::min;
88+
static constexpr auto max = rfl::config::enum_range<E>::max;
89+
};
90+
91+
template <UnscopedEnum E>
92+
requires SignedEnum<E> &&
93+
(!EnumFixedUnderlying<E>) && rfl::internal::enums::range_defined<E>
94+
struct enum_traits<E> {
95+
static constexpr auto min = rfl::config::enum_range<E>::min;
96+
static constexpr auto max = rfl::config::enum_range<E>::max;
97+
};
98+
99+
template <UnscopedEnum E>
100+
requires UnsignedEnum<E> &&
101+
(!EnumFixedUnderlying<E>) && rfl::internal::enums::range_defined<E>
102+
struct enum_traits<E> {
103+
static constexpr auto min = rfl::config::enum_range<E>::min;
104+
static constexpr auto max = rfl::config::enum_range<E>::max;
105+
};
106+
107+
} // namespace enchantum
108+
109+
namespace rfl::internal::enums::cpp20 {
110+
111+
template <enchantum::Enum EnumType>
112+
consteval auto get_enum_names() {
113+
return []<std::size_t... Is>(std::index_sequence<Is...>) {
114+
constexpr auto& entries = enchantum::entries<EnumType>;
115+
constexpr auto to_str_lit =
116+
[]<std::size_t... Js>(const char* name, std::index_sequence<Js...>) {
117+
return StringLiteral<sizeof...(Js) + 1>{name[Js]...};
118+
};
119+
return Names<EnumType,
120+
Literal<to_str_lit(
121+
entries[Is].second.data(),
122+
std::make_index_sequence<entries[Is].second.size()>{})...>,
123+
entries.size(), is_flag_enum<EnumType>,
124+
entries[Is].first...>{};
125+
}(std::make_index_sequence<enchantum::count<EnumType>>{});
126+
}
127+
} // namespace rfl::internal::enums::cpp20
128+
129+
#endif

include/rfl/internal/enums/range_defined.hpp renamed to include/rfl/internal/enums/cpp20/range_defined.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef RFL_INTERNAL_ENUMS_RANGE_DEFINED_HPP_
22
#define RFL_INTERNAL_ENUMS_RANGE_DEFINED_HPP_
33

4-
#include "../../config.hpp"
4+
#include "../../../config.hpp"
55

66
namespace rfl::internal::enums {
77

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef RFL_INTERNAL_ENUMS_CPP26_GET_ENUM_NAMES_HPP_
2+
#define RFL_INTERNAL_ENUMS_CPP26_GET_ENUM_NAMES_HPP_
3+
4+
#include <concepts>
5+
#include <meta>
6+
#include <utility>
7+
8+
#include "../../../Literal.hpp"
9+
#include "../Names.hpp"
10+
#include "../is_flag_enum.hpp"
11+
12+
namespace rfl::internal::enums::cpp26 {
13+
14+
template <class EnumType>
15+
consteval auto get_enum_names() {
16+
constexpr auto enumerators =
17+
std::define_static_array(std::meta::enumerators_of(^^EnumType));
18+
19+
constexpr auto [... is] = std::make_index_sequence<enumerators.size()>();
20+
21+
return Names<
22+
EnumType,
23+
Literal<StringLiteral<std::meta::identifier_of(enumerators[is]).size() +
24+
1>(std::meta::identifier_of(enumerators[is]))...>,
25+
enumerators.size(), is_flag_enum<EnumType>, ([:enumerators[is]:])...>{};
26+
}
27+
} // namespace rfl::internal::enums::cpp26
28+
29+
#endif
Lines changed: 11 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,23 @@
11
#ifndef RFL_INTERNAL_ENUMS_GET_ENUM_NAMES_HPP_
22
#define RFL_INTERNAL_ENUMS_GET_ENUM_NAMES_HPP_
33

4-
// Enum values must be greater than or equal to RFL_ENUM_RANGE_MIN.
5-
// By default, RFL_ENUM_RANGE_MIN is set to -256.
6-
// To change the default minimum range for all enum types, redefine the macro
7-
// RFL_ENUM_RANGE_MIN.
8-
#if !defined(RFL_ENUM_RANGE_MIN)
9-
#define RFL_ENUM_RANGE_MIN -256
4+
#ifndef REFLECTCPP_USE_CPP_REFLECTION
5+
#include "cpp20/get_enum_names.hpp"
6+
#else
7+
#include "cpp26/get_enum_names.hpp"
108
#endif
119

12-
// Enum values must be less than or equal to RFL_ENUM_RANGE_MAX.
13-
// By default, RFL_ENUM_RANGE_MAX is set to 256.
14-
// To change the default maximum range for all enum types, redefine the macro
15-
// RFL_ENUM_RANGE_MAX.
16-
#if !defined(RFL_ENUM_RANGE_MAX)
17-
#define RFL_ENUM_RANGE_MAX 256
18-
#endif
19-
20-
#ifdef ENCHANTUM_MIN_RANGE
21-
#undef ENCHANTUM_MIN_RANGE
22-
#endif
23-
#define ENCHANTUM_MIN_RANGE RFL_ENUM_RANGE_MIN
24-
25-
#ifdef ENCHANTUM_MAX_RANGE
26-
#undef ENCHANTUM_MAX_RANGE
27-
#endif
28-
#define ENCHANTUM_MAX_RANGE RFL_ENUM_RANGE_MAX
29-
30-
#include <concepts>
31-
#include <utility>
32-
33-
#include "../../thirdparty/enchantum/enchantum.hpp"// NOLINT(unused-includes)
34-
35-
#include "../../Literal.hpp"
36-
#include "Names.hpp"
37-
#include "range_defined.hpp"
38-
39-
// https://en.cppreference.com/w/cpp/language/static_cast:
40-
41-
// 8) A value of integer or enumeration type can be converted to any complete
42-
// enumeration type.
43-
44-
// If the underlying type is not fixed, the behavior is undefined if the value
45-
// of expression is out of range (the range is all values possible for the
46-
// smallest bit-field large enough to hold all enumerators of the target
47-
// enumeration). If the underlying type is fixed, the result is the same as
48-
// converting the original value first to the underlying type of the enumeration
49-
// and then to the enumeration type.
50-
51-
// https://en.cppreference.com/w/cpp/language/enum
52-
53-
// enum struct|class name { enumerator = constexpr , enumerator = constexpr ,
54-
// ... } (1)
55-
// ...
56-
// 1) declares a scoped enumeration type whose underlying type is int (the
57-
// keywords class and struct are exactly equivalent)
58-
//
59-
// --> These rules taken together imply that if you EITHER fix the type OR you
60-
// use a scoped integer, static_cast<MyEnum>(some_integer_value) will always be
61-
// defined.
62-
63-
template <enchantum::Enum E>
64-
requires requires(E e) {
65-
{ e | e } -> std::same_as<E>;
66-
}
67-
constexpr inline bool enchantum::is_bitflag<E> = true;
68-
69-
// Specialize the enchantum EnumTraits further, so rfl::config::enum_range
70-
// works.
71-
namespace enchantum {
72-
73-
template <SignedEnum E>
74-
requires rfl::internal::enums::range_defined<E>
75-
struct enum_traits<E> {
76-
static constexpr std::size_t prefix_length = 0;
77-
78-
static constexpr auto min = rfl::config::enum_range<E>::min;
79-
static constexpr auto max = rfl::config::enum_range<E>::max;
80-
};
81-
82-
template <UnsignedEnum E>
83-
requires rfl::internal::enums::range_defined<E>
84-
struct enum_traits<E> {
85-
static constexpr std::size_t prefix_length = 0;
86-
87-
static constexpr auto min = rfl::config::enum_range<E>::min;
88-
static constexpr auto max = rfl::config::enum_range<E>::max;
89-
};
90-
91-
template <UnscopedEnum E>
92-
requires SignedEnum<E> &&
93-
(!EnumFixedUnderlying<E>) && rfl::internal::enums::range_defined<E>
94-
struct enum_traits<E> {
95-
static constexpr auto min = rfl::config::enum_range<E>::min;
96-
static constexpr auto max = rfl::config::enum_range<E>::max;
97-
};
98-
99-
template <UnscopedEnum E>
100-
requires UnsignedEnum<E> &&
101-
(!EnumFixedUnderlying<E>) && rfl::internal::enums::range_defined<E>
102-
struct enum_traits<E> {
103-
static constexpr auto min = rfl::config::enum_range<E>::min;
104-
static constexpr auto max = rfl::config::enum_range<E>::max;
105-
};
106-
107-
} // namespace enchantum
108-
10910
namespace rfl::internal::enums {
11011

111-
template <enchantum::Enum EnumType>
12+
template <class EnumType>
11213
consteval auto get_enum_names() {
113-
return []<std::size_t... Is>(std::index_sequence<Is...>) {
114-
constexpr auto& entries = enchantum::entries<EnumType>;
115-
constexpr auto to_str_lit =
116-
[]<std::size_t... Js>(const char* name, std::index_sequence<Js...>) {
117-
return StringLiteral<sizeof...(Js) + 1>{name[Js]...};
118-
};
119-
return Names<EnumType,
120-
Literal<to_str_lit(
121-
entries[Is].second.data(),
122-
std::make_index_sequence<entries[Is].second.size()>{})...>,
123-
entries.size(), enchantum::is_bitflag<EnumType>,
124-
entries[Is].first...>{};
125-
}(std::make_index_sequence<enchantum::count<EnumType>>{});
14+
#ifndef REFLECTCPP_USE_CPP_REFLECTION
15+
return cpp20::get_enum_names<EnumType>();
16+
#else
17+
return cpp26::get_enum_names<EnumType>();
18+
#endif
12619
}
20+
12721
} // namespace rfl::internal::enums
12822

12923
#endif
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef RFL_INTERNAL_ENUMS_IS_FLAG_ENUM_HPP_
2+
#define RFL_INTERNAL_ENUMS_IS_FLAG_ENUM_HPP_
3+
4+
#include <concepts>
5+
6+
namespace rfl::internal::enums {
7+
8+
// Checks if an enum is a flag enum.
9+
template <class EnumType>
10+
inline constexpr bool is_flag_enum = requires(EnumType e) {
11+
{ e | e } -> std::same_as<EnumType>;
12+
};
13+
14+
} // namespace rfl::internal::enums
15+
16+
#endif

‎tests/json/test_enum8.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ struct SomeClass {
2727
};
2828

2929
TEST(json, test_enum8) {
30+
static_assert(rfl::internal::enums::is_flag_enum<TestEnum>);
31+
3032
SomeClass t{
3133
.e = TestEnum::None, .f = TestEnum::Hello, .g = TestEnum::HelloWorld};
3234

0 commit comments

Comments
 (0)