Как заставить enum класс работать с функцией bit-or?

Я обычно использую enum с «бит или» или | вместе, чтобы позволить объекту есть несколько вариантов. Как заставить enum класс работать с функцией bit-or?

8

Решение

Вам необходимо перегрузить операторы для вашего класса enum и реализовать их, приведя к базовому типу:

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 { };
15

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector