#pragma once #include "preprocessor.h" #include #include #include #include #include #include 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 void GetEnumTraitsImpl(T); template constexpr bool CanFitSubtype(); template using TEnumTraitsImpl = decltype(GetEnumTraitsImpl(T())); template constexpr std::optional TryGetEnumUnknownValueImpl(T); template < class T, bool DomainSizeKnown = requires{ TEnumTraitsImpl::DomainSize; } > struct TEnumTraitsWithKnownDomain { }; template < class T, bool = std::is_enum_v && !std::is_same_v, void> > struct TEnumTraits { static constexpr bool IsEnum = false; static constexpr bool IsBitEnum = false; static constexpr bool IsStringSerializableEnum = false; static constexpr bool IsMonotonic = false; }; template struct TEnumTraitsWithKnownDomain { static constexpr int GetDomainSize(); static constexpr const std::array& GetDomainNames(); static constexpr const std::array& GetDomainValues(); // For non-bit enums only. static constexpr T GetMinValue() requires (!TEnumTraitsImpl::IsBitEnum); static constexpr T GetMaxValue() requires (!TEnumTraitsImpl::IsBitEnum); // For bit enums only. static constexpr T GetAllSetValue() requires (TEnumTraitsImpl::IsBitEnum); static std::vector Decompose(T value) requires (TEnumTraitsImpl::IsBitEnum); }; template struct TEnumTraits : public TEnumTraitsWithKnownDomain { static constexpr bool IsEnum = true; static constexpr bool IsBitEnum = TEnumTraitsImpl::IsBitEnum; static constexpr bool IsStringSerializableEnum = TEnumTraitsImpl::IsStringSerializableEnum; static constexpr bool IsMonotonic = TEnumTraitsImpl::IsMonotonic; static TStringBuf GetTypeName(); static constexpr std::optional TryGetUnknownValue(); static std::optional FindLiteralByValue(T value); static std::optional FindValueByLiteral(TStringBuf literal); static constexpr bool IsKnownValue(T value) requires (!TEnumTraitsImpl::IsBitEnum); static constexpr bool IsValidValue(T value); static TString ToString(T value); static T FromString(TStringBuf literal); }; //////////////////////////////////////////////////////////////////////////////// //! Defines a smart enumeration with a specific underlying type. /*! * \param enumType Enumeration type. * \param seq Enumeration domain encoded as a sequence. * \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 type. * \param seq Enumeration domain encoded as a sequence. * \param underlyingType Underlying type. */ #define DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \ ENUM__CLASS(enumType, underlyingType, seq) \ ENUM__BITWISE_OPS(enumType) \ ENUM__BEGIN_TRAITS(enumType, underlyingType, true, false, seq) \ ENUM__VALIDATE_UNIQUE(enumType) \ ENUM__ALL_SET_VALUE(enumType, seq) \ ENUM__END_TRAITS(enumType) \ static_assert(true) //! Defines a smart enumeration with a specific underlying type. //! Duplicate enumeration values are allowed. /*! * \param enumType Enumeration type. * \param seq Enumeration domain encoded as a sequence. * \param underlyingType Underlying type. */ #define DEFINE_AMBIGUOUS_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \ ENUM__CLASS(enumType, underlyingType, seq) \ ENUM__BITWISE_OPS(enumType) \ ENUM__BEGIN_TRAITS(enumType, underlyingType, true, false, seq) \ ENUM__ALL_SET_VALUE(enumType, seq) \ ENUM__END_TRAITS(enumType) \ static_assert(true) //! Defines a smart enumeration with the default |unsigned int| underlying type. /*! * \param enumType Enumeration type. * \param seq Enumeration domain encoded as a sequence. */ #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 type. * \param seq Enumeration domain encoded as a sequence. * \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) //! When enum from another representation (e.g. string or protobuf integer), //! instructs the parser to treat undeclared values as |unknownValue|. /*! * \param enumType Enumeration type. * \param unknownValue A sentinel value of #enumType. */ #define DEFINE_ENUM_UNKNOWN_VALUE(enumType, unknownValue) \ [[maybe_unused]] constexpr std::optional TryGetEnumUnknownValueImpl(enumType) \ { \ return enumType::unknownValue; \ } //////////////////////////////////////////////////////////////////////////////// //! Returns |true| iff the enumeration value is not bitwise zero. template requires TEnumTraits::IsBitEnum constexpr bool Any(E value) noexcept; //! Returns |true| iff the enumeration value is bitwise zero. template requires TEnumTraits::IsBitEnum constexpr bool None(E value) noexcept; //////////////////////////////////////////////////////////////////////////////// } // namespace NYT #define ENUM_INL_H_ #include "enum-inl.h" #undef ENUM_INL_H_