2
\$\begingroup\$

I use c++ 11 enum class usually instead of the old enums because many enums can contain the same value but as known they don't have the bitwise operators out of the box so we should define them manually

in windows it's already done for us with this macro in windows.h header :

DEFINE_ENUM_FLAG_OPERATORS

but I then encountered another problem

if I use these enum as flags I can put many values in the falg using bitwise operator | , but to test if the flag contains a value I can't check with bitwise operator & like this :

if (flags & value) {...}

I could however write a template function like this to test :

template <class T>
constexpr bool has_value(T flags, T value)
{
    return (std::underlying_type_t<T>)flags & (std::underlying_type_t<T>)value;
}

but I really would like to use the old format to test for values in the flags I already found a solution on github which wrapped all chosen emums in a class called flags and it was used like the old ones but with the type safety of enum classes

As I don't want to use templates for this purpose and I want only operator & to give me a bool value in if expressions , I used another class that holds the enum value and can be converted to bool and this is what I wrote

#define OVERLOAD_ENUM_OPERATORS(x) \
class EnumBool##x \
{ \
    x enum_value; \
public: \
    constexpr EnumBool##x(const x e_val) : enum_value(e_val) {} \
    constexpr operator x() const { return enum_value; } \
    explicit operator bool() const { return (std::underlying_type_t<x>)enum_value != 0; } \
}; \
inline constexpr EnumBool##x operator&(const x lhs, const x rhs) \
{ \
    return EnumBool##x((x)((std::underlying_type_t<x>)lhs & (std::underlying_type_t<x>)rhs)); \
} \
inline constexpr x operator|(const x lhs, const x rhs) \
{ \
    return (x)((std::underlying_type_t<x>)lhs | (std::underlying_type_t<x>)rhs); \
} \
inline constexpr x operator^(const x lhs, const x rhs) \
{ \
    return (x)((std::underlying_type_t<x>)lhs ^ (std::underlying_type_t<x>)rhs);\
} \
inline constexpr x operator~(const x lhs) \
{ \
    return (x)(~(std::underlying_type_t<x>)lhs);\
} \
inline constexpr x& operator|=(x& lhs, const x rhs) \
{ \
    lhs = (x)((std::underlying_type_t<x>)lhs | (std::underlying_type_t<x>)rhs); \
    return lhs; \
} \
inline constexpr x& operator&=(x& lhs, const x rhs) \
{ \
    lhs = (x)((std::underlying_type_t<x>)lhs & (std::underlying_type_t<x>)rhs); \
    return lhs; \
} \
inline constexpr x& operator^=(x& lhs, const x rhs) \
{ \
    lhs = (x)((std::underlying_type_t<x>)lhs ^ (std::underlying_type_t<x>)rhs); \
    return lhs; \
} \
inline constexpr bool operator==(const x lhs, const x rhs) \
{ \
    return (std::underlying_type_t<x>)lhs == (std::underlying_type_t<x>)rhs; \
} \
inline constexpr bool operator!=(const x lhs, const x rhs) \
{ \
    return (std::underlying_type_t<x>)lhs != (std::underlying_type_t<x>)rhs; \
} \
inline constexpr bool operator>(const x lhs, const x rhs) \
{ \
    return (std::underlying_type_t<x>)lhs > (std::underlying_type_t<x>)rhs; \
} \
inline constexpr bool operator<(const x lhs, const x rhs) \
{ \
    return (std::underlying_type_t<x>)lhs < (std::underlying_type_t<x>)rhs; \
} \
inline constexpr bool operator>=(const x lhs, const x rhs) \
{ \
    return (std::underlying_type_t<x>)lhs >= (std::underlying_type_t<x>)rhs; \
} \
inline constexpr bool operator<=(const x lhs, const x rhs) \
{ \
    return (std::underlying_type_t<x>)lhs <= (std::underlying_type_t<x>)rhs; \
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Is there a reason, why you don't want use templates? \$\endgroup\$ – JulianH Aug 22 at 17:26
  • \$\begingroup\$ Do you know that you can overload operators for enum class, just like the standard does for std::byte? \$\endgroup\$ – L. F. Aug 25 at 12:32
1
\$\begingroup\$

A few things that might be improved:

  • Use static_cast<type>(value) instead of (type)(value).
  • I'm missing an bool operator!(const x lhs).
  • You could also define operator&& and operator||.
  • You can make enum_value const.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.