#pragma once #include // This tiny header is to define value ranges at compile time in enums and enum class/struct types. // // enum class E1 { // A, // B, // C, // }; // Y_DEFINE_ENUM_MINMAX(E1, A, C); // // or // // enum class E2 { // A, // B, // C, // }; // Y_DEFINE_ENUM_MAX(E2, C); // // Notes: // * use Y_DEFINE_ENUM_MINMAX / Y_DEFINE_ENUM_MINMAX if your enum is defined in a namespace // * use Y_DEFINE_ENUM_MINMAX_F / Y_DEFINE_ENUM_MINMAX_F if your enum is defined in a class/struct // * use shortened version Y_DEFINE_ENUM_MAX / Y_DEFINE_ENUM_MAX_F if enum begin is 0 // * add Y_DEFINE_xxx macro immediately after enum definition // // Usage examples: // TEnumRange::Min // min value of range in enum type // TEnumRange::Max // max value of range in enum type // TEnumRange::UnderlyingMin // min value of range in underlying type // TEnumRange::UnderlyingMax // max value of range in underlying type void _YRegisterEnumRange(...); namespace NDetail::NEnumRange { template struct TEnumRange { static_assert(std::is_enum_v, ""); using TEnum = E; using TUnderlying = std::underlying_type_t; static constexpr TEnum Min = _Min; static constexpr TEnum Max = _Max; static constexpr TUnderlying UnderlyingMin = static_cast(Min); static constexpr TUnderlying UnderlyingMax = static_cast(Max); static_assert(UnderlyingMin <= UnderlyingMax, "Invalid enum range"); }; } #define Y_DEFINE_ENUM_MINMAX_IMPL(PREFIX, E, Min, Max) \ PREFIX ::NDetail::NEnumRange::TEnumRange _YRegisterEnumRange(const E*) #define Y_DEFINE_ENUM_MINMAX(E, Min, Max) \ Y_DEFINE_ENUM_MINMAX_IMPL([[maybe_unused]], E, E::Min, E::Max) #define Y_DEFINE_ENUM_MAX(E, Max) \ Y_DEFINE_ENUM_MINMAX_IMPL([[maybe_unused]], E, E{}, E::Max) #define Y_DEFINE_ENUM_MINMAX_FRIEND(E, Min, Max) \ Y_DEFINE_ENUM_MINMAX_IMPL(friend, E, E::Min, E::Max) #define Y_DEFINE_ENUM_MAX_FRIEND(E, Max) \ Y_DEFINE_ENUM_MINMAX_IMPL(friend, E, E{}, E::Max) template using TEnumRange = decltype(_YRegisterEnumRange(static_cast(nullptr)));