1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
#pragma once
#include <type_traits>
// This tiny header is to define value ranges at compile time in enums and enum class/struct types.
//
// enum class E1 {
// A,
// B,
// C,
// };
// Y_DEFINE_ENUM_MINMAX(E1, A, C);
//
// or
//
// enum class E2 {
// A,
// B,
// C,
// };
// Y_DEFINE_ENUM_MAX(E2, C);
//
// Notes:
// * use Y_DEFINE_ENUM_MINMAX / Y_DEFINE_ENUM_MINMAX if your enum is defined in a namespace
// * use Y_DEFINE_ENUM_MINMAX_F / Y_DEFINE_ENUM_MINMAX_F if your enum is defined in a class/struct
// * use shortened version Y_DEFINE_ENUM_MAX / Y_DEFINE_ENUM_MAX_F if enum begin is 0
// * add Y_DEFINE_xxx macro immediately after enum definition
//
// Usage examples:
// TEnumRange<E>::Min // min value of range in enum type
// TEnumRange<E>::Max // max value of range in enum type
// TEnumRange<E>::UnderlyingMin // min value of range in underlying type
// TEnumRange<E>::UnderlyingMax // max value of range in underlying type
void _YRegisterEnumRange(...);
namespace NDetail::NEnumRange {
template <typename E, E _Min, E _Max>
struct TEnumRange {
static_assert(std::is_enum_v<E>, "");
using TEnum = E;
using TUnderlying = std::underlying_type_t<TEnum>;
static constexpr TEnum Min = _Min;
static constexpr TEnum Max = _Max;
static constexpr TUnderlying UnderlyingMin = static_cast<TUnderlying>(Min);
static constexpr TUnderlying UnderlyingMax = static_cast<TUnderlying>(Max);
static_assert(UnderlyingMin <= UnderlyingMax, "Invalid enum range");
};
}
#define Y_DEFINE_ENUM_MINMAX_IMPL(PREFIX, E, Min, Max) \
PREFIX ::NDetail::NEnumRange::TEnumRange<E, Min, Max> _YRegisterEnumRange(const E*)
#define Y_DEFINE_ENUM_MINMAX(E, Min, Max) \
Y_DEFINE_ENUM_MINMAX_IMPL([[maybe_unused]], E, E::Min, E::Max)
#define Y_DEFINE_ENUM_MAX(E, Max) \
Y_DEFINE_ENUM_MINMAX_IMPL([[maybe_unused]], E, E{}, E::Max)
#define Y_DEFINE_ENUM_MINMAX_FRIEND(E, Min, Max) \
Y_DEFINE_ENUM_MINMAX_IMPL(friend, E, E::Min, E::Max)
#define Y_DEFINE_ENUM_MAX_FRIEND(E, Max) \
Y_DEFINE_ENUM_MINMAX_IMPL(friend, E, E{}, E::Max)
template <typename E>
using TEnumRange = decltype(_YRegisterEnumRange(static_cast<E*>(nullptr)));
|