diff options
author | babenko <babenko@yandex-team.com> | 2023-03-14 09:33:31 +0300 |
---|---|---|
committer | babenko <babenko@yandex-team.com> | 2023-03-14 09:33:31 +0300 |
commit | e10767756146ca0d8e890326e20671aed5182e2b (patch) | |
tree | 0d15dded16242ddb4d7b64f5e1d21d425742234e /library/cpp/yt/misc/enum.h | |
parent | 9aa65dc165f24925a281f89c975cc5117823934f (diff) | |
download | ydb-e10767756146ca0d8e890326e20671aed5182e2b.tar.gz |
YT-18571: Refactor YT enums to make them Arcadia-friendly
Diffstat (limited to 'library/cpp/yt/misc/enum.h')
-rw-r--r-- | library/cpp/yt/misc/enum.h | 183 |
1 files changed, 103 insertions, 80 deletions
diff --git a/library/cpp/yt/misc/enum.h b/library/cpp/yt/misc/enum.h index 1353900996..773e1ac4ed 100644 --- a/library/cpp/yt/misc/enum.h +++ b/library/cpp/yt/misc/enum.h @@ -4,9 +4,9 @@ #include <util/generic/strbuf.h> -#include <stdexcept> -#include <type_traits> #include <array> +#include <optional> +#include <type_traits> #include <vector> #include <library/cpp/yt/exception/exception.h> @@ -22,15 +22,33 @@ namespace NYT { * (unittests/enum_ut.cpp). */ -// Actual overload must be provided with defines DEFINE_ENUM_XXX (see below). +// The actual overload must be provided with DEFINE_ENUM* (see below). template <class T> void GetEnumTraitsImpl(T); +template <class T> +using TEnumTraitsImpl = decltype(GetEnumTraitsImpl(T())); + +template <class T> +constexpr bool IsEnumDomainSizeKnown() +{ + if constexpr(requires{ TEnumTraitsImpl<T>::DomainSize; }) { + return true; + } else { + return false; + } +} + template < class T, - bool = std::is_enum<T>::value && - !std::is_convertible<T, int>::value && - !std::is_same<void, decltype(GetEnumTraitsImpl(T()))>::value + bool = IsEnumDomainSizeKnown<T>() +> +struct TEnumTraitsWithKnownDomain +{ }; + +template < + class T, + bool = std::is_enum_v<T> && !std::is_same_v<TEnumTraitsImpl<T>, void> > struct TEnumTraits { @@ -40,124 +58,122 @@ struct TEnumTraits }; template <class T> -struct TEnumTraits<T, true> +struct TEnumTraitsWithKnownDomain<T, true> { - using TImpl = decltype(GetEnumTraitsImpl(T())); - using TType = T; - using TUnderlying = typename TImpl::TUnderlying; - - static constexpr bool IsEnum = true; - static constexpr bool IsBitEnum = TImpl::IsBitEnum; - static constexpr bool IsStringSerializableEnum = TImpl::IsStringSerializableEnum; + static constexpr int GetDomainSize(); - static constexpr int DomainSize = TImpl::DomainSize; + static constexpr const std::array<TStringBuf, GetDomainSize()>& GetDomainNames(); + static constexpr const std::array<T, GetDomainSize()>& GetDomainValues(); - static TStringBuf GetTypeName(); + // For non-bit enums only. + static constexpr T GetMinValue() + requires (!TEnumTraitsImpl<T>::IsBitEnum); + static constexpr T GetMaxValue() + requires (!TEnumTraitsImpl<T>::IsBitEnum); - static const TStringBuf* FindLiteralByValue(TType value); - static bool FindValueByLiteral(TStringBuf literal, TType* result); + // For bit enums only. + static std::vector<T> Decompose(T value) + requires (TEnumTraitsImpl<T>::IsBitEnum); +}; - static const std::array<TStringBuf, DomainSize>& GetDomainNames(); - static const std::array<TType, DomainSize>& GetDomainValues(); +template <class T> +struct TEnumTraits<T, true> + : public TEnumTraitsWithKnownDomain<T> +{ + static constexpr bool IsEnum = true; + static constexpr bool IsBitEnum = TEnumTraitsImpl<T>::IsBitEnum; + static constexpr bool IsStringSerializableEnum = TEnumTraitsImpl<T>::IsStringSerializableEnum; - static TType FromString(TStringBuf str); - static TString ToString(TType value); + static TStringBuf GetTypeName(); - // For non-bit enums only. - static constexpr TType GetMinValue(); - static constexpr TType GetMaxValue(); + static std::optional<TStringBuf> FindLiteralByValue(T value); + static std::optional<T> FindValueByLiteral(TStringBuf literal); - // For bit enums only. - static std::vector<TType> Decompose(TType value); + static TString ToString(T value); + static T FromString(TStringBuf literal); }; //////////////////////////////////////////////////////////////////////////////// //! Defines a smart enumeration with a specific underlying type. /*! - * \param name Enumeration name. + * \param enumType Enumeration enumType. * \param seq Enumeration domain encoded as a <em>sequence</em>. * \param underlyingType Underlying type. */ -#define DEFINE_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ - ENUM__CLASS(name, underlyingType, seq) \ - ENUM__BEGIN_TRAITS(name, underlyingType, false, false, seq) \ - ENUM__MINMAX \ - ENUM__VALIDATE_UNIQUE(name) \ - ENUM__END_TRAITS(name) +#define DEFINE_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \ + ENUM__CLASS(enumType, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(enumType, underlyingType, false, false, seq) \ + ENUM__VALIDATE_UNIQUE(enumType) \ + ENUM__END_TRAITS(enumType) //! Defines a smart enumeration with a specific underlying type. //! Duplicate enumeration values are allowed. -#define DEFINE_AMBIGUOUS_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ - ENUM__CLASS(name, underlyingType, seq) \ - ENUM__BEGIN_TRAITS(name, underlyingType, false, false, seq) \ - ENUM__MINMAX \ - ENUM__END_TRAITS(name) +#define DEFINE_AMBIGUOUS_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \ + ENUM__CLASS(enumType, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(enumType, underlyingType, false, false, seq) \ + ENUM__END_TRAITS(enumType) //! Defines a smart enumeration with the default |int| underlying type. -#define DEFINE_ENUM(name, seq) \ - DEFINE_ENUM_WITH_UNDERLYING_TYPE(name, int, seq) +#define DEFINE_ENUM(enumType, seq) \ + DEFINE_ENUM_WITH_UNDERLYING_TYPE(enumType, int, seq) //! Defines a smart enumeration with a specific underlying type. /*! - * \param name Enumeration name. + * \param enumType Enumeration enumType. * \param seq Enumeration domain encoded as a <em>sequence</em>. * \param underlyingType Underlying type. */ -#define DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ - ENUM__CLASS(name, underlyingType, seq) \ - ENUM__BEGIN_TRAITS(name, underlyingType, true, false, seq) \ - ENUM__DECOMPOSE \ - ENUM__VALIDATE_UNIQUE(name) \ - ENUM__END_TRAITS(name) \ - ENUM__BITWISE_OPS(name) +#define DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \ + ENUM__CLASS(enumType, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(enumType, underlyingType, true, false, seq) \ + ENUM__VALIDATE_UNIQUE(enumType) \ + ENUM__END_TRAITS(enumType) \ + ENUM__BITWISE_OPS(enumType) //! Defines a smart enumeration with a specific underlying type. //! Duplicate enumeration values are allowed. /*! - * \param name Enumeration name. + * \param enumType Enumeration enumType. * \param seq Enumeration domain encoded as a <em>sequence</em>. * \param underlyingType Underlying type. */ -#define DEFINE_AMBIGUOUS_BIT_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ - ENUM__CLASS(name, underlyingType, seq) \ - ENUM__BEGIN_TRAITS(name, underlyingType, true, false, seq) \ - ENUM__DECOMPOSE \ - ENUM__END_TRAITS(name) \ - ENUM__BITWISE_OPS(name) - -//! Defines a smart enumeration with the default |unsigned| underlying type. +#define DEFINE_AMBIGUOUS_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \ + ENUM__CLASS(enumType, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(enumType, underlyingType, true, false, seq) \ + ENUM__END_TRAITS(enumType) \ + ENUM__BITWISE_OPS(enumType) + +//! Defines a smart enumeration with the default |unsigned int| underlying type. /*! - * \param name Enumeration name. + * \param enumType Enumeration enumType. * \param seq Enumeration domain encoded as a <em>sequence</em>. */ -#define DEFINE_BIT_ENUM(name, seq) \ - DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(name, unsigned, seq) +#define DEFINE_BIT_ENUM(enumType, seq) \ + DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, unsigned int, seq) //! Defines a smart enumeration with a specific underlying type and IsStringSerializable attribute. /*! - * \param name Enumeration name. + * \param enumType Enumeration enumType. * \param seq Enumeration domain encoded as a <em>sequence</em>. * \param underlyingType Underlying type. */ -#define DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ - ENUM__CLASS(name, underlyingType, seq) \ - ENUM__BEGIN_TRAITS(name, underlyingType, false, true, seq) \ - ENUM__MINMAX \ - ENUM__VALIDATE_UNIQUE(name) \ - ENUM__END_TRAITS(name) \ +#define DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \ + ENUM__CLASS(enumType, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(enumType, underlyingType, false, true, seq) \ + ENUM__VALIDATE_UNIQUE(enumType) \ + ENUM__END_TRAITS(enumType) \ //! Defines a smart enumeration with a specific underlying type and IsStringSerializable attribute. //! Duplicate enumeration values are allowed. -#define DEFINE_AMBIGUOUS_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(name, underlyingType, seq) \ - ENUM__CLASS(name, underlyingType, seq) \ - ENUM__BEGIN_TRAITS(name, underlyingType, false, true, seq) \ - ENUM__MINMAX \ - ENUM__END_TRAITS(name) +#define DEFINE_AMBIGUOUS_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \ + ENUM__CLASS(enumType, underlyingType, seq) \ + ENUM__BEGIN_TRAITS(enumType, underlyingType, false, true, seq) \ + ENUM__END_TRAITS(enumType) //! Defines a smart enumeration with the default |int| underlying type and IsStringSerializable attribute. -#define DEFINE_STRING_SERIALIZABLE_ENUM(name, seq) \ - DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(name, int, seq) +#define DEFINE_STRING_SERIALIZABLE_ENUM(enumType, seq) \ + DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(enumType, int, seq) //////////////////////////////////////////////////////////////////////////////// @@ -199,20 +215,27 @@ public: static bool IsDomainValue(E value); private: - using TUnderlying = typename TEnumTraits<E>::TUnderlying; + using TUnderlying = std::underlying_type_t<E>; static constexpr int N = static_cast<TUnderlying>(Max) - static_cast<TUnderlying>(Min) + 1; std::array<T, N> Items_; }; //////////////////////////////////////////////////////////////////////////////// +//! Replace with |std::to_underlying| in C++23. +template <typename E> + requires std::is_enum_v<E> +constexpr std::underlying_type_t<E> ToUnderlying(E value) noexcept; + //! Returns |true| iff the enumeration value is not bitwise zero. -template <typename E, typename = std::enable_if_t<NYT::TEnumTraits<E>::IsBitEnum, E>> -bool Any(E value); +template <typename E> + requires TEnumTraits<E>::IsBitEnum +constexpr bool Any(E value) noexcept; //! Returns |true| iff the enumeration value is bitwise zero. -template <typename E, typename = std::enable_if_t<NYT::TEnumTraits<E>::IsBitEnum, E>> -bool None(E value); +template <typename E> + requires TEnumTraits<E>::IsBitEnum +constexpr bool None(E value) noexcept; //////////////////////////////////////////////////////////////////////////////// |