c++enumsunderlyingtype

Any benefits to declare an enum class underlying type bool?


In the library I am currently developing, I have this little thing:

enum class BoolMode : uint8_t
{
    TrueIfFalse = 0,
    TrueIfTrue  = 1
};

This is a tiny helper used to easily produce reversible condition checks, while only having to create a single implementation that's easy to write and to read...

For this helper to be effectively easy to use, I had to define the comparison operator for bool (obviously). I did it like that:

inline constexpr bool operator ==(const bool boolValue, const BoolMode mode) noexcept
{
    return (boolValue == static_cast<const bool>(mode));
}

inline constexpr bool operator !=(const bool boolValue, const BoolMode mode) noexcept
{
    return (boolValue != static_cast<const bool>(mode));
}

inline constexpr bool operator ==(const BoolMode mode, const bool boolValue) noexcept
{
    return (boolValue == static_cast<const bool>(mode));
}

inline constexpr bool operator !=(const BoolMode mode, const bool boolValue) noexcept
{
    return (boolValue != static_cast<const bool>(mode));
}

I was wondering if there would have any benefits to define BoolMode this way:

enum class BoolMode : bool
{
    TrueIfFalse = false,
    TrueIfTrue  = true
};

As it does not spare the effort to have to define the comparison operators anyway, I don't see what the best option would be...

Questions:

Thanks in advance.


Solution

  • If bool is the underlying type of X, then std::underlying_type_t<X> is bool.

    Variables of type bool and enums with bool underlying type only have two valid states; 0 and 1.

    Variables of type uint8_t and enums with uint8_t underlying type has 256 valid states; 0 through 255.

    Both a compiler, and metaprogramming, can be aware of this difference. A custom notstd::optional could use the fact that 3 is not a valid bool to make notstd::optional<bool> take up a single byte (its value would be 0 for false, 1 for true and 3 for nullopt).

    This could also be used to smart-pack bools or enums with bool underlying type into bit-fields when serialized.

    In theory, the assembly generated for == when bool is the underlying type could do a bit comparison instead of zero or non-zero byte check. I could imagine platforms where that is faster. Meanwhile, if uint8_t was the underlying type, a non-zero value anywhere in the enum means it maps to true when cast to bool.

    None of these issues are likely.