是否可以定义一个宏来定义枚举类,并使用GetCount()方法返回枚举元素的数量?

时间:2019-02-07 13:49:46

标签: c++ c++17

我能够定义一个宏,该宏定义了一个老式的枚举,并且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; }};

但这不能编译,因为 VA_ARGS 应该以'EnumName ::'开头。

1 个答案:

答案 0 :(得分:2)

枚举

如注释中所建议,至于您的第一个宏DEFINE_FLAGS_ENUMstd::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>中的 enum 进行计数:

#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);