aboutsummaryrefslogtreecommitdiffstats
path: root/util/generic/enum_range.h
diff options
context:
space:
mode:
authorchezzie <chezzie@yandex-team.com>2024-06-25 09:54:31 +0300
committerchezzie <chezzie@yandex-team.com>2024-06-25 10:06:56 +0300
commite166004e08f4ea69899364beaae07218fc351e95 (patch)
tree1d0f83ed69b4964ef39d2813b1c85a6e223c9b73 /util/generic/enum_range.h
parent509c9fc9e7b9c3b8be7307d72a4c966e5f9aa194 (diff)
downloadydb-e166004e08f4ea69899364beaae07218fc351e95.tar.gz
Enum range to util
Изолированный хидер, не должен ничего поломать Почему решил не завязываться и не расширять GENERATE_ENUM_SERIALIZATION[_WITH_HEADER): 1) Нет возможности добавлять метаданные для енамов объявленных в cpp 2) Нет возможности добавлять метаданные для енамов объявленных в anonymous namespace 3) Нет возможности использовать метаданные в том же хидере, где объявлен enum В первую очередь будет использован в библиотеке range_containers - https://a.yandex-team.ru/arcadia/market/library/range_containers/ 74cd8c66052608f1b6fec69c39cb0f868376fe0a
Diffstat (limited to 'util/generic/enum_range.h')
-rw-r--r--util/generic/enum_range.h72
1 files changed, 72 insertions, 0 deletions
diff --git a/util/generic/enum_range.h b/util/generic/enum_range.h
new file mode 100644
index 0000000000..a9f78a291e
--- /dev/null
+++ b/util/generic/enum_range.h
@@ -0,0 +1,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)));