enum.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #pragma once
  2. #include "preprocessor.h"
  3. #include <util/generic/strbuf.h>
  4. #include <array>
  5. #include <optional>
  6. #include <type_traits>
  7. #include <vector>
  8. #include <library/cpp/yt/exception/exception.h>
  9. namespace NYT {
  10. ////////////////////////////////////////////////////////////////////////////////
  11. /*
  12. * Smart enumerations augment C++ enum classes with a bunch of reflection
  13. * capabilities accessible via TEnumTraits class specialization.
  14. *
  15. * Please refer to the unit test for an actual example of usage
  16. * (unittests/enum_ut.cpp).
  17. */
  18. // The actual overload must be provided with DEFINE_ENUM* (see below).
  19. template <class T>
  20. void GetEnumTraitsImpl(T);
  21. template <class T, class S>
  22. constexpr bool CanFitSubtype();
  23. template <class T>
  24. using TEnumTraitsImpl = decltype(GetEnumTraitsImpl(T()));
  25. template <class T>
  26. constexpr bool IsEnumDomainSizeKnown()
  27. {
  28. if constexpr(requires{ TEnumTraitsImpl<T>::DomainSize; }) {
  29. return true;
  30. } else {
  31. return false;
  32. }
  33. }
  34. template <
  35. class T,
  36. bool = IsEnumDomainSizeKnown<T>()
  37. >
  38. struct TEnumTraitsWithKnownDomain
  39. { };
  40. template <
  41. class T,
  42. bool = std::is_enum_v<T> && !std::is_same_v<TEnumTraitsImpl<T>, void>
  43. >
  44. struct TEnumTraits
  45. {
  46. static constexpr bool IsEnum = false;
  47. static constexpr bool IsBitEnum = false;
  48. static constexpr bool IsStringSerializableEnum = false;
  49. static constexpr bool IsMonotonic = false;
  50. };
  51. template <class T>
  52. struct TEnumTraitsWithKnownDomain<T, true>
  53. {
  54. static constexpr int GetDomainSize();
  55. static constexpr const std::array<TStringBuf, GetDomainSize()>& GetDomainNames();
  56. static constexpr const std::array<T, GetDomainSize()>& GetDomainValues();
  57. // For non-bit enums only.
  58. static constexpr T GetMinValue()
  59. requires (!TEnumTraitsImpl<T>::IsBitEnum);
  60. static constexpr T GetMaxValue()
  61. requires (!TEnumTraitsImpl<T>::IsBitEnum);
  62. // For bit enums only.
  63. static std::vector<T> Decompose(T value)
  64. requires (TEnumTraitsImpl<T>::IsBitEnum);
  65. };
  66. template <class T>
  67. struct TEnumTraits<T, true>
  68. : public TEnumTraitsWithKnownDomain<T>
  69. {
  70. static constexpr bool IsEnum = true;
  71. static constexpr bool IsBitEnum = TEnumTraitsImpl<T>::IsBitEnum;
  72. static constexpr bool IsStringSerializableEnum = TEnumTraitsImpl<T>::IsStringSerializableEnum;
  73. static constexpr bool IsMonotonic = TEnumTraitsImpl<T>::IsMonotonic;
  74. static TStringBuf GetTypeName();
  75. static std::optional<TStringBuf> FindLiteralByValue(T value);
  76. static std::optional<T> FindValueByLiteral(TStringBuf literal);
  77. static TString ToString(T value);
  78. static T FromString(TStringBuf literal);
  79. };
  80. ////////////////////////////////////////////////////////////////////////////////
  81. //! Defines a smart enumeration with a specific underlying type.
  82. /*!
  83. * \param enumType Enumeration enumType.
  84. * \param seq Enumeration domain encoded as a <em>sequence</em>.
  85. * \param underlyingType Underlying type.
  86. */
  87. #define DEFINE_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
  88. ENUM__CLASS(enumType, underlyingType, seq) \
  89. ENUM__BEGIN_TRAITS(enumType, underlyingType, false, false, seq) \
  90. ENUM__VALIDATE_UNIQUE(enumType) \
  91. ENUM__END_TRAITS(enumType) \
  92. static_assert(true)
  93. //! Defines a smart enumeration with a specific underlying type.
  94. //! Duplicate enumeration values are allowed.
  95. #define DEFINE_AMBIGUOUS_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
  96. ENUM__CLASS(enumType, underlyingType, seq) \
  97. ENUM__BEGIN_TRAITS(enumType, underlyingType, false, false, seq) \
  98. ENUM__END_TRAITS(enumType) \
  99. static_assert(true)
  100. //! Defines a smart enumeration with the default |int| underlying type.
  101. #define DEFINE_ENUM(enumType, seq) \
  102. DEFINE_ENUM_WITH_UNDERLYING_TYPE(enumType, int, seq)
  103. //! Defines a smart enumeration with a specific underlying type.
  104. /*!
  105. * \param enumType Enumeration enumType.
  106. * \param seq Enumeration domain encoded as a <em>sequence</em>.
  107. * \param underlyingType Underlying type.
  108. */
  109. #define DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
  110. ENUM__CLASS(enumType, underlyingType, seq) \
  111. ENUM__BEGIN_TRAITS(enumType, underlyingType, true, false, seq) \
  112. ENUM__VALIDATE_UNIQUE(enumType) \
  113. ENUM__END_TRAITS(enumType) \
  114. ENUM__BITWISE_OPS(enumType) \
  115. static_assert(true)
  116. //! Defines a smart enumeration with a specific underlying type.
  117. //! Duplicate enumeration values are allowed.
  118. /*!
  119. * \param enumType Enumeration enumType.
  120. * \param seq Enumeration domain encoded as a <em>sequence</em>.
  121. * \param underlyingType Underlying type.
  122. */
  123. #define DEFINE_AMBIGUOUS_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
  124. ENUM__CLASS(enumType, underlyingType, seq) \
  125. ENUM__BEGIN_TRAITS(enumType, underlyingType, true, false, seq) \
  126. ENUM__END_TRAITS(enumType) \
  127. ENUM__BITWISE_OPS(enumType) \
  128. static_assert(true)
  129. //! Defines a smart enumeration with the default |unsigned int| underlying type.
  130. /*!
  131. * \param enumType Enumeration enumType.
  132. * \param seq Enumeration domain encoded as a <em>sequence</em>.
  133. */
  134. #define DEFINE_BIT_ENUM(enumType, seq) \
  135. DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, unsigned int, seq)
  136. //! Defines a smart enumeration with a specific underlying type and IsStringSerializable attribute.
  137. /*!
  138. * \param enumType Enumeration enumType.
  139. * \param seq Enumeration domain encoded as a <em>sequence</em>.
  140. * \param underlyingType Underlying type.
  141. */
  142. #define DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
  143. ENUM__CLASS(enumType, underlyingType, seq) \
  144. ENUM__BEGIN_TRAITS(enumType, underlyingType, false, true, seq) \
  145. ENUM__VALIDATE_UNIQUE(enumType) \
  146. ENUM__END_TRAITS(enumType) \
  147. static_assert(true)
  148. //! Defines a smart enumeration with a specific underlying type and IsStringSerializable attribute.
  149. //! Duplicate enumeration values are allowed.
  150. #define DEFINE_AMBIGUOUS_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
  151. ENUM__CLASS(enumType, underlyingType, seq) \
  152. ENUM__BEGIN_TRAITS(enumType, underlyingType, false, true, seq) \
  153. ENUM__END_TRAITS(enumType) \
  154. static_assert(true)
  155. //! Defines a smart enumeration with the default |int| underlying type and IsStringSerializable attribute.
  156. #define DEFINE_STRING_SERIALIZABLE_ENUM(enumType, seq) \
  157. DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(enumType, int, seq)
  158. ////////////////////////////////////////////////////////////////////////////////
  159. //! Returns |true| iff the enumeration value is not bitwise zero.
  160. template <typename E>
  161. requires TEnumTraits<E>::IsBitEnum
  162. constexpr bool Any(E value) noexcept;
  163. //! Returns |true| iff the enumeration value is bitwise zero.
  164. template <typename E>
  165. requires TEnumTraits<E>::IsBitEnum
  166. constexpr bool None(E value) noexcept;
  167. ////////////////////////////////////////////////////////////////////////////////
  168. } // namespace NYT
  169. #define ENUM_INL_H_
  170. #include "enum-inl.h"
  171. #undef ENUM_INL_H_