是否可以定义一个宏来定义枚举类和返回枚举元素计数的 GetCount() 方法



我能够定义定义旧式枚举和返回枚举元素计数的 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::"为前缀。

枚举

正如评论中所建议的,至于您的第一个宏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>中的枚举元素计算为私有成员:

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

然后我们可以定义一个枚举和枚举类,如下所示:

演示

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

最新更新