|
5 | 5 | #include <utility> |
6 | 6 | #include <rsl/meta_traits> |
7 | 7 |
|
| 8 | +#include <rsl/_impl/traits.hpp> |
| 9 | + |
8 | 10 | namespace rsl { |
9 | 11 | inline namespace annotations { |
10 | 12 | struct FlagEnumTag {}; |
@@ -127,43 +129,6 @@ struct numeric_limits<E> { |
127 | 129 | static constexpr const std::float_round_style round_style = std::round_toward_zero; |
128 | 130 | }; |
129 | 131 |
|
130 | | -namespace _impl { |
131 | | -template <class T> |
132 | | -inline const bool is_signed_integer_v = false; |
133 | | -template <> |
134 | | -inline const bool is_signed_integer_v<signed char> = true; |
135 | | -template <> |
136 | | -inline const bool is_signed_integer_v<signed short> = true; |
137 | | -template <> |
138 | | -inline const bool is_signed_integer_v<signed int> = true; |
139 | | -template <> |
140 | | -inline const bool is_signed_integer_v<signed long> = true; |
141 | | -template <> |
142 | | -inline const bool is_signed_integer_v<signed long long> = true; |
143 | | - |
144 | | -template <class T> |
145 | | -inline const bool is_unsigned_integer_v = false; |
146 | | -template <> |
147 | | -inline const bool is_unsigned_integer_v<unsigned char> = true; |
148 | | -template <> |
149 | | -inline const bool is_unsigned_integer_v<unsigned short> = true; |
150 | | -template <> |
151 | | -inline const bool is_unsigned_integer_v<unsigned int> = true; |
152 | | -template <> |
153 | | -inline const bool is_unsigned_integer_v<unsigned long> = true; |
154 | | -template <> |
155 | | -inline const bool is_unsigned_integer_v<unsigned long long> = true; |
156 | | - |
157 | | -template <class T> |
158 | | -concept signed_integer = is_signed_integer_v<T>; |
159 | | - |
160 | | -template <class T> |
161 | | -concept unsigned_integer = is_unsigned_integer_v<T>; |
162 | | - |
163 | | -template <class T> |
164 | | -concept integer_type = signed_integer<T> or unsigned_integer<T>; |
165 | | -} // namespace _impl |
166 | | - |
167 | 132 | template <is_fixed_enum E> |
168 | 133 | requires is_fixed_enum<E> and (not is_flag_enum<E>) |
169 | 134 | struct numeric_limits<E> : std::numeric_limits<std::underlying_type_t<E>> {}; |
@@ -196,73 +161,6 @@ constexpr bool in_range(U value) noexcept { |
196 | 161 | std::cmp_greater_equal(static_cast<underlying>(value), |
197 | 162 | static_cast<underlying>(numeric_limits<T>::min())); |
198 | 163 | } |
199 | | - |
200 | | -namespace _impl { |
201 | | -template <typename T> |
202 | | -struct Enumerator { |
203 | | - T value; |
204 | | - char const* name; |
205 | | -}; |
206 | | - |
207 | | -template <typename T> |
208 | | -consteval auto enum_pairs() { |
209 | | - auto enumerators = |
210 | | - std::vector(std::from_range, enumerators_of(^^T) | std::views::transform([](auto e) { |
211 | | - return Enumerator(extract<T>(constant_of(e)), |
212 | | - define_static_string(identifier_of(e))); |
213 | | - })); |
214 | | - |
215 | | - using sort_t = std::make_unsigned_t<std::underlying_type_t<T>>; |
216 | | - std::ranges::stable_sort(enumerators, std::ranges::greater{}, [](auto const& e) { |
217 | | - return std::popcount(static_cast<sort_t>(e.value)); |
218 | | - }); |
219 | | - |
220 | | - return enumerators; |
221 | | -} |
222 | | -} // namespace _impl |
223 | | - |
224 | | -template <typename T> |
225 | | - requires std::is_enum_v<T> |
226 | | -constexpr std::string to_string(T value) { |
227 | | - if constexpr (is_flag_enum<T>) { |
228 | | - // for flag-likes we want to support `A | B` unless we got exact match |
229 | | - constexpr static auto enums = std::define_static_array(_impl::enum_pairs<T>()); |
230 | | - |
231 | | - auto remainder = std::to_underlying(value); |
232 | | - std::vector<std::string_view> partial; |
233 | | - |
234 | | - for (auto [v, name] : enums) { |
235 | | - if (v == 0) { |
236 | | - if (remainder == 0) { |
237 | | - return name; |
238 | | - } |
239 | | - } else if ((remainder & v) == v) { |
240 | | - remainder &= ~v; |
241 | | - partial.push_back(name); |
242 | | - if (remainder == 0) { |
243 | | - break; |
244 | | - } |
245 | | - } |
246 | | - } |
247 | | - |
248 | | - auto ret = std::string(std::from_range, partial | std::views::join_with('|')); |
249 | | - if (remainder != 0) { |
250 | | - return ret + identifier_of(^^T) + "(" + to_string(remainder) + ")"; |
251 | | - } |
252 | | - return ret; |
253 | | - } else { |
254 | | - // otherwise we can do better - try generating a switch instead |
255 | | - template for (constexpr auto E : define_static_array(enumerators_of(^^T))) { |
256 | | - if (extract<T>(constant_of(E)) == value) { |
257 | | - // at least one enumerator was an exact match, print the first |
258 | | - return std::string{identifier_of(E)}; |
259 | | - } |
260 | | - } |
261 | | - // still no match, print as cast using the functional notation |
262 | | - return std::string(identifier_of(^^T)) + "(" + to_string(std::to_underlying(value)) + ")"; |
263 | | - } |
264 | | -} |
265 | | - |
266 | 164 | } // namespace rsl |
267 | 165 |
|
268 | 166 | #ifdef RSL_POISON_STD |
|
0 commit comments