Something is wrong with the following code, can you spot what it is? (If in doubt, try compiling it.)
enum class Color { red = 1, green = 2, blue = 4 };
auto yellow = Color::red | Color::green;
As you may have found out, the compiler complains with a message such as: error: no match for 'operator|' (operand types are 'Color' and 'Color')
. The simplistic solution is to remove the class
keyword, and use the “plain” enum
type, where the enumerators are implicitly convertible to and from int
.
Alternatively we could grab the bull by the horns and try to define operator|
(bitwise-or) for Color
. The language allows this, but first we must find a way of extracting a type that can be operated upon, from the enum class
definition. Luckily, the Standard Library comes to our rescue with the utility underlying_type<T>
found in the <type_traits>
header. (Note that we should not just assume that this type is int
as it can be any integral or boolean type; interestingly the ability to set the underlying type has been backported to plain enum
in Modern C++.)
So get ready for some casts, three in total – two from the Color
parameters to the underlying type, and one back to Color
for the return type. Here is the complete function (which needs both the <type_traits>
header and enum class
definition from before):
constexpr Color operator| (Color lhs, Color rhs) {
using underlying_t = typename std::underlying_type<Color>::type;
return static_cast<Color>(
static_cast<underlying_t>(lhs)
| static_cast<underlying_t>(rhs)
);
}
This function can be used to define operator|
for any other enum class
by changing the five occurrences of Color
, thus enabling use as a bitfield. Here it has been declared constexpr
so that these bitfields can be calculated for use at compile-time. If you choose to use this method, the important thing to remember is all those static_cast
s which ensure the bitwise-or operation cannot lose precision. It is of course possible to define other operators such as &
(bitwise-and) and ~
(bitwise-complement) using similar code.