Reputation: 4305
I was able to define macro that defines an old-style enum and GetCount() method returning the count of enum elements:
#define DEFINE_FLAGS_ENUM(EnumName, ...) \
struct EnumName { \
enum { __VA_ARGS__ }; \
static constexpr std::size_t GetCount() { return std::max({__VA_ARGS__}) + 1;} \
};
With enum class my first idea was:
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; }};
but this does not compile, because VA_ARGS should be prepended with 'EnumName::'.
Upvotes: 2
Views: 218
Reputation: 2880
enum
As suggested in comments, as for your first macro DEFINE_FLAGS_ENUM
, std::max
does not seem to work.
Thus I propose an alternative way for it.
Since our enum
is defined as an anonymous one in the class EnumName
, we can define the tuple of them and detect the size of it at compile-time as follows.
So this macro would well work for you:
#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
For the enum class
, we can reuse the above method as follows.
Here, instead of counting the elements of enum class, we again count the ones of enum which is hidden in the class EnumTraits<EnumName>
as a private member:
#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; \
} \
};
Then we can define an enum and enum class as follows:
// 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);
Upvotes: 3