123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- #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>
- 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)
- ////////////////////////////////////////////////////////////////////////////////
- //! A statically sized vector with elements of type |T| indexed by
- //! the items of enumeration type |E|.
- /*!
- * Items are value-initialized on construction.
- */
- template <
- class E,
- class T,
- E Min = TEnumTraits<E>::GetMinValue(),
- E Max = TEnumTraits<E>::GetMaxValue()
- >
- class TEnumIndexedVector
- {
- public:
- using TIndex = E;
- using TValue = T;
- constexpr TEnumIndexedVector();
- constexpr TEnumIndexedVector(std::initializer_list<T> elements);
- constexpr TEnumIndexedVector(const TEnumIndexedVector&) = default;
- constexpr TEnumIndexedVector(TEnumIndexedVector&&) noexcept = default;
- constexpr TEnumIndexedVector& operator=(const TEnumIndexedVector&) = default;
- constexpr TEnumIndexedVector& operator=(TEnumIndexedVector&&) noexcept = default;
- T& operator[] (E index);
- const T& operator[] (E index) const;
- // STL interop.
- T* begin();
- const T* begin() const;
- T* end();
- const T* end() const;
- static bool IsDomainValue(E value);
- private:
- 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_;
- };
- ////////////////////////////////////////////////////////////////////////////////
- //! 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_
|