How to make enum class to work with the 'bit-or' feature?

时光毁灭记忆、已成空白 提交于 2019-11-30 13:00:07

You need to overload the operators for your enum class and implement them by casting to the underlying type:

enum class foo : unsigned {
    bar = 1,
    baz = 2
};

foo operator |(foo a, foo b) {
    return static_cast<foo>(static_cast<unsigned>(a) | static_cast<unsigned>(b));
}

… of course this could be generalised (using SFINAE and std::underlying_type). That C++ doesn’t provide this out of the box is an oversight, in my opinion.

Here’s how a general implementation might look like:

// Intentionally undefined for non-enum types.
template <typename T, bool = std::is_enum<T>::value>
struct is_flag;

template <typename T>
struct is_flag<T, true> : std::false_type { };

template <typename T, typename std::enable_if<is_flag<T>::value>::type* = nullptr>
T operator |(T lhs, T rhs) {
    using u_t = typename std::underlying_type<T>::type;
    return static_cast<T>(static_cast<u_t>(lhs) | static_cast<u_t>(rhs));
}

// … same for `&`, `~`. And maybe functions like `isset`, `set` and `unset`.

This implementation ensures that the overload is only found for enums that are actually acting as flags. To mark an enum as a flag, you need to specialise is_flag:

enum class a_flag : unsigned {
    foo = 0,
    bar = 1,
    baz = 2
};

template <> struct is_flag<a_flag> : std::true_type { };
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!