OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
define_enum_class.h
Go to the documentation of this file.
1 /*
2  * Copyright 2023 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
38 #pragma once
39 
40 #include <boost/preprocessor.hpp>
41 
42 #include <algorithm>
43 #include <array>
44 #include <optional>
45 #include <ostream>
46 #include <string_view>
47 
48 #define HEAVYAI_DEFINE_ENUM_CLASS(enum_class, ...) \
49  enum class enum_class { __VA_ARGS__, N_ }; \
50  \
51  constexpr char const* to_string(enum_class const e) { \
52  constexpr char const* strings[]{HEAVYAI_QUOTE_EACH(__VA_ARGS__)}; \
53  constexpr size_t nstrings = sizeof(strings) / sizeof(*strings); \
54  static_assert(nstrings == size_t(enum_class::N_)); \
55  return strings[size_t(e)]; \
56  } \
57  \
58  inline std::ostream& operator<<(std::ostream& os, enum_class const e) { \
59  return os << to_string(e); \
60  }
61 
62 #define HEAVYAI_DEFINE_ENUM_CLASS_WITH_DESCRIPTIONS(enum_class, ...) \
63  HEAVYAI_DEFINE_ENUM_CLASS(enum_class, HEAVYAI_PLUCK(0, __VA_ARGS__)) \
64  \
65  constexpr char const* to_description(enum_class const e) { \
66  constexpr char const* strings[]{HEAVYAI_PLUCK(1, __VA_ARGS__)}; \
67  constexpr size_t nstrings = sizeof(strings) / sizeof(*strings); \
68  static_assert(nstrings == size_t(enum_class::N_)); \
69  return strings[size_t(e)]; \
70  }
71 
72 // Helper macros
73 #define HEAVYAI_QUOTE(r, data, i, elem) BOOST_PP_COMMA_IF(i) BOOST_PP_STRINGIZE(elem)
74 #define HEAVYAI_QUOTE_EACH(...) \
75  BOOST_PP_SEQ_FOR_EACH_I(HEAVYAI_QUOTE, , BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
76 #define HEAVYAI_PLUCK_ONE(r, j, i, pair) \
77  BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, j, pair)
78 #define HEAVYAI_PLUCK(j, ...) \
79  BOOST_PP_SEQ_FOR_EACH_I(HEAVYAI_PLUCK_ONE, j, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
80 
81 namespace heavyai {
82 
83 // Helper function and struct templates
84 template <typename Enum>
85 struct StringEnum {
86  std::string_view name;
87  Enum value;
88 
89  bool operator<(std::string_view const name) const { return this->name < name; }
90 };
91 
92 template <typename Enum, size_t... I>
93 constexpr auto enum_to_array(std::index_sequence<I...>) {
94  return std::array<StringEnum<Enum>, sizeof...(I)>{
95  StringEnum<Enum>{to_string(static_cast<Enum>(I)), static_cast<Enum>(I)}...};
96 }
97 
98 template <typename T, size_t N>
99 constexpr void insertion_sort(std::array<T, N>& arr) {
100  for (size_t i = 1; i < N; ++i) {
101  auto key = arr[i];
102  size_t j = i;
103  for (; j && key.name < arr[j - 1].name; --j) {
104  arr[j] = arr[j - 1];
105  }
106  arr[j] = key;
107  }
108 }
109 
110 template <typename Enum>
111 constexpr std::array<StringEnum<Enum>, size_t(Enum::N_)> sort_by_name() {
112  auto arr = enum_to_array<Enum>(std::make_index_sequence<size_t(Enum::N_)>());
113  insertion_sort(arr);
114  return arr;
115 }
116 
117 // Return std::optional<Enum> given string name in O(log(Enum::N_)) time and stack space.
118 template <typename Enum>
119 std::optional<Enum> to_enum(std::string_view const name) {
120  constexpr std::array<StringEnum<Enum>, size_t(Enum::N_)> arr = sort_by_name<Enum>();
121  auto const itr = std::lower_bound(arr.begin(), arr.end(), name);
122  bool const found = itr != arr.end() && itr->name == name;
123  return found ? std::make_optional(itr->value) : std::nullopt;
124 }
125 
126 // Example: IsAny<Color::Red, Color::Green, Color::Blue>::check(Color::Blue);
127 template <auto... Values>
128 struct IsAny {
129  template <typename T>
130  static bool check(T const value) {
131  // Casting to T allows for safe comparison against out-of-range value.
132  // Example: IsAny<Color::Red, Color::Green, Color::Blue>::check(-1);
133  return ((static_cast<T>(Values) == value) || ...);
134  }
135 };
136 
137 } // namespace heavyai
bool operator<(std::string_view const name) const
constexpr std::array< StringEnum< Enum >, size_t(Enum::N_)> sort_by_name()
std::string to_string(const UUID &uuid)
Definition: uuid.h:110
constexpr auto enum_to_array(std::index_sequence< I...>)
std::optional< Enum > to_enum(std::string_view const name)
constexpr void insertion_sort(std::array< T, N > &arr)
DEVICE auto lower_bound(ARGS &&...args)
Definition: gpu_enabled.h:78
constexpr unsigned N
Definition: Utm.h:110
std::string_view name
string name
Definition: setup.in.py:72
static bool check(T const value)