123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- #pragma once
- #include "preprocessor.h"
- #include <util/generic/strbuf.h>
- #include <array>
- #include <optional>
- #include <type_traits>
- #include <vector>
- #include <library/cpp/yt/exception/exception.h>
- namespace NYT {
- ////////////////////////////////////////////////////////////////////////////////
- /*
- * Smart enumerations augment C++ enum classes with a bunch of reflection
- * capabilities accessible via TEnumTraits class specialization.
- *
- * Please refer to the unit test for an actual example of usage
- * (unittests/enum_ut.cpp).
- */
- // The actual overload must be provided with DEFINE_ENUM* (see below).
- template <class T>
- void GetEnumTraitsImpl(T);
- template <class T, class S>
- constexpr bool CanFitSubtype();
- 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 = IsEnumDomainSizeKnown<T>()
- >
- struct TEnumTraitsWithKnownDomain
- { };
- template <
- class T,
- bool = std::is_enum_v<T> && !std::is_same_v<TEnumTraitsImpl<T>, void>
- >
- struct TEnumTraits
- {
- static constexpr bool IsEnum = false;
- static constexpr bool IsBitEnum = false;
- static constexpr bool IsStringSerializableEnum = false;
- static constexpr bool IsMonotonic = false;
- };
- template <class T>
- struct TEnumTraitsWithKnownDomain<T, true>
- {
- static constexpr int GetDomainSize();
- static constexpr const std::array<TStringBuf, GetDomainSize()>& GetDomainNames();
- static constexpr const std::array<T, GetDomainSize()>& GetDomainValues();
- // For non-bit enums only.
- static constexpr T GetMinValue()
- requires (!TEnumTraitsImpl<T>::IsBitEnum);
- static constexpr T GetMaxValue()
- requires (!TEnumTraitsImpl<T>::IsBitEnum);
- // For bit enums only.
- static std::vector<T> Decompose(T value)
- requires (TEnumTraitsImpl<T>::IsBitEnum);
- };
- 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 constexpr bool IsMonotonic = TEnumTraitsImpl<T>::IsMonotonic;
- static TStringBuf GetTypeName();
- static std::optional<TStringBuf> FindLiteralByValue(T value);
- static std::optional<T> FindValueByLiteral(TStringBuf literal);
- static TString ToString(T value);
- static T FromString(TStringBuf literal);
- };
- ////////////////////////////////////////////////////////////////////////////////
- //! Defines a smart enumeration with a specific underlying type.
- /*!
- * \param enumType Enumeration enumType.
- * \param seq Enumeration domain encoded as a <em>sequence</em>.
- * \param underlyingType Underlying type.
- */
- #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) \
- static_assert(true)
- //! Defines a smart enumeration with a specific underlying type.
- //! Duplicate enumeration values are allowed.
- #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) \
- static_assert(true)
- //! Defines a smart enumeration with the default |int| underlying type.
- #define DEFINE_ENUM(enumType, seq) \
- DEFINE_ENUM_WITH_UNDERLYING_TYPE(enumType, int, seq)
- //! Defines a smart enumeration with a specific underlying type.
- /*!
- * \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(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) \
- static_assert(true)
- //! Defines a smart enumeration with a specific underlying type.
- //! Duplicate enumeration values are allowed.
- /*!
- * \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(enumType, underlyingType, seq) \
- ENUM__CLASS(enumType, underlyingType, seq) \
- ENUM__BEGIN_TRAITS(enumType, underlyingType, true, false, seq) \
- ENUM__END_TRAITS(enumType) \
- ENUM__BITWISE_OPS(enumType) \
- static_assert(true)
- //! Defines a smart enumeration with the default |unsigned int| underlying type.
- /*!
- * \param enumType Enumeration enumType.
- * \param seq Enumeration domain encoded as a <em>sequence</em>.
- */
- #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 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(enumType, underlyingType, seq) \
- ENUM__CLASS(enumType, underlyingType, seq) \
- ENUM__BEGIN_TRAITS(enumType, underlyingType, false, true, seq) \
- ENUM__VALIDATE_UNIQUE(enumType) \
- ENUM__END_TRAITS(enumType) \
- static_assert(true)
- //! 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(enumType, underlyingType, seq) \
- ENUM__CLASS(enumType, underlyingType, seq) \
- ENUM__BEGIN_TRAITS(enumType, underlyingType, false, true, seq) \
- ENUM__END_TRAITS(enumType) \
- static_assert(true)
- //! Defines a smart enumeration with the default |int| underlying type and IsStringSerializable attribute.
- #define DEFINE_STRING_SERIALIZABLE_ENUM(enumType, seq) \
- DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(enumType, int, seq)
- ////////////////////////////////////////////////////////////////////////////////
- //! Returns |true| iff the enumeration value is not bitwise zero.
- 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>
- requires TEnumTraits<E>::IsBitEnum
- constexpr bool None(E value) noexcept;
- ////////////////////////////////////////////////////////////////////////////////
- } // namespace NYT
- #define ENUM_INL_H_
- #include "enum-inl.h"
- #undef ENUM_INL_H_
|