4
\$\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\$
2
  • 1
    \$\begingroup\$Is there a reason, why you don't want use templates?\$\endgroup\$
    – JulianW
    CommentedAug 22, 2019 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.
    CommentedAug 25, 2019 at 12:32

1 Answer 1

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\$

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.