如何使枚举类与'bit-or'功能一起使用?

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

本文关键字:一起 功能 bit-or 枚举 何使      更新时间:2023-10-16

我通常将enum与"bit-or"或|一起使用,以允许对象有一些选项。如何使枚举类与"位或"功能一起使用?

您需要重载枚举类的运算符,并通过强制转换为底层类型来实现它们:

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));
}

。当然,这可以推广(使用SFINAE和std::underlying_type)。在我看来,C++没有提供开箱即用的这个是一个疏忽。

下面是一般实现的外观:

// 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`.

此实现可确保仅为实际充当标志的枚举找到重载。要将枚举标记为标志,您需要专门is_flag

enum class a_flag : unsigned {
    foo = 0,
    bar = 1,
    baz = 2
};
template <> struct is_flag<a_flag> : std::true_type { };