分享
三行代码  ›  专栏  ›  技术社区  ›  Alexey Starinsky

是否可以定义定义枚举类的宏,以及返回枚举元素计数的getCount()方法? - Is it possible to define a macro that defines an enum class and GetCount() method returning the count of enum elements?

  •  2
  • Alexey Starinsky  · 技术社区  · 8 月前

    我能够定义定义一个旧样式枚举的宏,getCount()方法返回枚举元素的计数:

    #define DEFINE_FLAGS_ENUM(EnumName, ...) \
    struct EnumName { \
        enum { __VA_ARGS__ }; \
        static constexpr std::size_t GetCount() { return std::max({__VA_ARGS__}) + 1;} \
    };
    

    对于枚举类,我的第一个想法是:

    template <class T> struct EnumTraits;
    
    #define NDA_FLAGS_ENUM(EnumName, ...) \
    enum class EnumName { __VA_ARGS__ }; \
    template<> struct EnumTraits<EnumName> { static constexpr std::size_t GetCount() { return std::max({__VA_ARGS__}) + 1; }};
    

    但这并不能编译,因为 瓦尔阿格斯 应以“EnumName::”开头。

    1 回复  |  直到 8 月前
        1
  •  2
  •   Hiroki    8 月前

    DEFINE_FLAGS_ENUM std::max

    enum EnumName

    #include <tuple>
    
    #define DEFINE_FLAGS_ENUM(EnumName, ...)                  \
    struct EnumName                                           \
    {                                                         \
        enum { __VA_ARGS__ };                                 \
                                                              \
        static constexpr std::size_t GetCount()               \
        {                                                     \
            using T = decltype(std::make_tuple(__VA_ARGS__)); \
            return std::tuple_size<T>::value;                 \
        }                                                     \
    };
    

    enum class EnumTraits<EnumName>

    #include <tuple>
    
    template <class T> struct EnumTraits;
    
    #define NDA_FLAGS_ENUM(EnumName, ...)                     \
    enum class EnumName { __VA_ARGS__ };                      \
    template<>                                                \
    struct EnumTraits<EnumName>                               \
    {                                                         \
    private:                                                  \
        enum { __VA_ARGS__ };                                 \
                                                              \
    public:                                                   \
        static constexpr std::size_t GetCount()               \
        {                                                     \
            using T = decltype(std::make_tuple(__VA_ARGS__)); \
            return std::tuple_size<T>::value;                 \
        }                                                     \
    };
    

    DEMO

    // enum.
    DEFINE_FLAGS_ENUM(Animal, Dog, Cat)
    static_assert(Animal::GetCount() == 2);
    
    // enum class.
    NDA_FLAGS_ENUM(Vehicle, Car, Train, AirPlain)
    static_assert(EnumTraits<Vehicle>::GetCount() == 3);