Можно ли определить макрос, который определяет класс enum и метод GetCount (), возвращающий количество элементов enum? - PullRequest
0 голосов
/ 07 февраля 2019

Я смог определить макрос, который определяет enum старого стиля и метод GetCount (), возвращающий количество элементов enum:

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

С классом enum моя первая идея была:

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 голосов
/ 07 февраля 2019

enum

Как предлагается в комментариях, как и для вашего первого макроса 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

Для enum class мы можем использовать вышеописанный метод следующим образом.Здесь вместо подсчета элементов класса enum мы снова считаем элементы enum , которые скрыты в классе 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...