#pragma once #include #include #include #include namespace ore { namespace detail::EnumUtil { int FindIndex(int value, const IterRange& values); void Parse(const IterRange& out, StringView definition); constexpr int CountValues(const char* text_all, size_t text_all_len) { int count = 1; for (size_t i = 0; i < text_all_len; ++i) { if (text_all[i] == ',') ++count; } return count; } } // namespace detail::EnumUtil template struct Enum { public: Enum() { T::Init(); } static Enum& Info() { return s_Info; } StringView name{}; IterRange members{}; private: static inline Enum s_Info{}; }; #define ORE_ENUM(NAME, ...) \ class NAME { \ public: \ enum Type { __VA_ARGS__ }; \ \ static void Init() { \ static ore::StringView names[cCount]; \ ore::detail::EnumUtil::Parse(ore::IterRange(names), cTextAll); \ ore::Enum::Info().name = #NAME; \ ore::Enum::Info().members = ore::IterRange(names); \ } \ \ static constexpr int Size() { return cCount; } \ static constexpr Type Invalid() { return Type(Size()); } \ \ private: \ static constexpr const char* cTextAll = #__VA_ARGS__; \ static constexpr size_t cTextAllLen = sizeof(#__VA_ARGS__); \ static constexpr int cCount = ore::detail::EnumUtil::CountValues(cTextAll, cTextAllLen); \ }; // FIXME template class ValuedEnum { public: ValuedEnum() { T::Init(); } static Enum& Info() { return s_Info; } StringView name{}; IterRange members{}; private: static inline Enum s_Info{}; }; #define ORE_VALUED_ENUM(NAME, ...) \ class NAME { \ public: \ enum Type { __VA_ARGS__ }; \ \ static void Init() { \ static ore::StringView names[cCount]; \ ore::detail::EnumUtil::Parse(ore::IterRange(names), cTextAll); \ ore::ValuedEnum::Info().name = #NAME; \ ore::ValuedEnum::Info().members = ore::IterRange(names); \ } \ \ static constexpr int Size() { return cCount; } \ static constexpr Type Invalid() { return Type(Size()); } \ \ private: \ static constexpr const char* cTextAll = #__VA_ARGS__; \ static constexpr size_t cTextAllLen = sizeof(#__VA_ARGS__); \ static constexpr int cCount = ore::detail::EnumUtil::CountValues(cTextAll, cTextAllLen); \ }; /// For storing an enum with a particular storage size when specifying the underlying type of the /// enum is not an option. template struct SizedEnum { static_assert(std::is_enum()); static_assert(!std::is_enum()); constexpr SizedEnum() = default; constexpr SizedEnum(Enum value) { *this = value; } constexpr operator Enum() const { return static_cast(mValue); } constexpr SizedEnum& operator=(Enum value) { mValue = static_cast(value); return *this; } Storage mValue; }; } // namespace ore