1 #pragma once 2 3 #include <algorithm> 4 #include <array> 5 #include <stdexcept> 6 #include <string> 7 8 namespace utils 9 { 10 11 template <class T> 12 struct EnumTraits 13 { 14 [[noreturn]] static void throwConversionError() 15 { 16 throw std::out_of_range("Value is not in range of enum"); 17 } 18 }; 19 20 template <class T, T first, T last> 21 inline T toEnum(std::underlying_type_t<T> x) 22 { 23 if (x < static_cast<std::underlying_type_t<T>>(first) || 24 x > static_cast<std::underlying_type_t<T>>(last)) 25 { 26 EnumTraits<T>::throwConversionError(); 27 } 28 return static_cast<T>(x); 29 } 30 31 template <class T> 32 constexpr inline std::underlying_type_t<T> toUnderlying(T value) 33 { 34 return static_cast<std::underlying_type_t<T>>(value); 35 } 36 37 template <class T, size_t N> 38 constexpr inline T 39 minEnumValue(std::array<std::pair<std::string_view, T>, N> data) 40 { 41 auto min = data[0].second; 42 for (auto [key, value] : data) 43 { 44 if (toUnderlying(min) > toUnderlying(value)) 45 { 46 min = value; 47 } 48 } 49 return min; 50 } 51 52 template <class T, size_t N> 53 constexpr inline T 54 maxEnumValue(std::array<std::pair<std::string_view, T>, N> data) 55 { 56 auto max = data[0].second; 57 for (auto [key, value] : data) 58 { 59 if (toUnderlying(max) < toUnderlying(value)) 60 { 61 max = value; 62 } 63 } 64 return max; 65 } 66 67 template <class T, size_t N> 68 inline T toEnum(const std::array<std::pair<std::string_view, T>, N>& data, 69 const std::string& value) 70 { 71 auto it = std::find_if( 72 std::begin(data), std::end(data), 73 [&value](const auto& item) { return item.first == value; }); 74 if (it == std::end(data)) 75 { 76 EnumTraits<T>::throwConversionError(); 77 } 78 return it->second; 79 } 80 81 template <class T, size_t N> 82 inline std::string_view 83 enumToString(const std::array<std::pair<std::string_view, T>, N>& data, 84 T value) 85 { 86 auto it = std::find_if( 87 std::begin(data), std::end(data), 88 [value](const auto& item) { return item.second == value; }); 89 if (it == std::end(data)) 90 { 91 EnumTraits<T>::throwConversionError(); 92 } 93 return it->first; 94 } 95 96 } // namespace utils 97