Реализация перечисления с использованием оператора |
Моя проблема заключается в том, что мне нужно реализовать возможность перечисления доступных для записи типов Severity, используемых в сообщениях. Это необходимо для того, чтобы иметь возможность фильтровать сообщения по степени серьезности в классе Logger. Severity является enum классом:
enum class Severity: uint8_t
{
EMERGENCY = 0, // System is unusable
ALERT = 1, // Action must be taken immediately
CRITICAL = 2, // Critical conditions
ERROR = 3, // Error conditions
WARNING = 4, // Warning conditions
NOTICE = 5, // Normal but significant condition
INFO = 6, // Informational
DEBUG = 7, // Debug level messages
};
На данный момент я вижу только одно действующие решения этой проблемы. А решение состоит в том, чтобы иметь два открытых метода в классе Logger:
void addSeverity(Severity severity);
void rmvSeverity(Severity severity);
которые будут отвечать за добавление и удаление типов серьезности. Например, если определенное Severity добавлено, игнорирование сообщений с таким типом производится не будет.
Но мне бы хотелось, иметь такую возможность, указанную в коде ниже (в данном случае, мы будем иметь возможность записывать лишь 3 типа Severity):
void setSeveritySupports(Severity);
// ...
setSeveritySupports(Severity::INFO | Severity::WARNING | Severity::ERROR);
Я могу перегрузить оператор | таким способом :
Severity operator|(Severity l, Severity r)
{
return Severity(static_cast<int>(l) | static_cast<int>(r));
}
но в таком случае, я максимум что могу, это установть максимальное значение Severity.
Ответы (1 шт):
Что-то типа такого?
enum Severity : uint8_t
{
EMERGENCY = 0x01, // System is unusable
ALERT = 0x02, // Action must be taken immediately
CRITICAL = 0x04, // Critical conditions
ERROR = 0x08, // Error conditions
WARNING = 0x10, // Warning conditions
NOTICE = 0x20, // Normal but significant condition
INFO = 0x40, // Informational
DEBUG = 0x80, // Debug level messages
};
inline const char* severityToString(uint8_t sev) {
switch (sev) {
case EMERGENCY: return "Emergency";
case ALERT: return "Alert";
case CRITICAL: return "Critical";
case ERROR: return "Error";
case WARNING: return "Warning";
case NOTICE: return "Notice";
case INFO: return "Info";
case DEBUG: return "Debug";
default: return "";
}
}
void setSeveritySupports(uint8_t flag) {
uint8_t tmp = flag;
uint8_t mask = 0x1;
while (tmp > 0) {
if(tmp & 1)
cout << "Установлен флаг: " << severityToString(flag & mask) << endl;
mask <<= 1;
tmp >>= 1;
}
}
int main()
{
setlocale(LC_ALL, "Russian");
setSeveritySupports(Severity::ALERT | Severity::INFO | Severity::ERROR | Severity::DEBUG);
return 0;
}
Результат программы:
Используем в качестве значений степени двойки, т.к. возьмем 2 числа являющиеся степенями двойки, например 64 и 8, в двоичной системе счисления они будут выглядеть так:
64 = ...0010000
8 = ...0000100
Воспользовавшись оператором | (побитовое ИЛИ), мы сможем упаковать эти два числа в одно.
64 = ...0010000 |
8 = ...0000100 =
20 = ...0010100
И теперь по этому числу мы сможем получить обратно число 64 и 8.
По ссылке которую предложил wololo вы можете почитать об этой теме.
P.s. Так как у вас 8 значений в enum, то максимальное значение будет `2^
