Использование Qt
Q_FLAGS_NS
не поддерживает побитовые операции: он просто регистрирует тип в система метаобъектов Qt.
Если вы хотите зарегистрировать тип и обеспечить побитовую поддержку оператора, вам следует использовать QFlags.
Пример из документации:
class MyClass
{
public:
enum Option {
NoOptions = 0x0,
ShowTabs = 0x1,
ShowAll = 0x2,
SqueezeBlank = 0x4
};
Q_DECLARE_FLAGS(Options, Option)
...
};
Q_DECLARE_OPERATORS_FOR_FLAGS(MyClass::Options)
Вы также можете просто пропустить большую часть этого и сделать:
// not type-safe, unscoped enum. You should likely define this
// in a namespace or class.
enum Option {
NoOptions = 0x0,
ShowTabs = 0x1,
ShowAll = 0x2,
SqueezeBlank = 0x4
};
// type-safe flag
using Options = QFlags<Option>;
Вы также можете использовать перечисления без области для этой цели или использовать макрос, который поможет вам обеспечить поддержку побитового оператора для перечисления с областью действия:
Безопасные типы побитовых операций с перечислениями в области видимости
Вот макрос, который вы можете свободно использовать (общественное достояние, мой собственный код, хотя вам, вероятно, следует изменить макрос, чтобы убедиться, что он имеет префикс, чтобы избежать любых конфликтов имен), чтобы добавить побитовые операции в перечисление с областью видимости. В настоящее время для этого требуется поддержка C++14, однако изменение std::underlying_type_t<T>
на typename std::underlying_type<T>::type
позволяет макросу работать в C++11.
Использовать
enum class enum1_t
{
A = 1,
B,
C,
D,
E,
};
enum class enum2_t
{
F = 1,
G,
H,
I,
J,
};
ENUM_FLAG(enum1_t) // allow bitwise operations for enum1_t and enum1_t
ENUM_FLAG(enum1_t, enum2_t) // allow bitwise operations for enum1_t and enum2_t
Код
#include <type_traits>
#include <cstdint>
// HELPERS
// -------
/**
* \brief Get enum underlying type.
*/
template <typename T>
inline std::underlying_type_t<T> int_t(T t)
{
return static_cast<std::underlying_type_t<T>>(t);
}
// MACROS
// ------
/**
* \brief Macro to define enum operators between enumerations.
*
* Supports `&`, `&=`, `|`, `|=`, `^`, `^=`, `~`, and bool conversion.
*/
#define ENUM_FLAG2(lhs_t, ths_t) \
/* \brief Bitwise or operator. */ \
inline lhs_t operator|(lhs_t lhs, ths_t rhs) noexcept \
{ \
return static_cast<lhs_t>(int_t(lhs) | int_t(rhs)); \
} \
\
/* \brief Bitwise or assignment operator. */ \
inline lhs_t & operator|=(lhs_t &lhs, ths_t rhs) noexcept \
{ \
lhs = static_cast<lhs_t>(int_t(lhs) | int_t(rhs)); \
return lhs; \
} \
\
/* \brief Bitwise and operator. */ \
inline lhs_t operator&(lhs_t lhs, ths_t rhs) noexcept \
{ \
return static_cast<lhs_t>(int_t(lhs) & int_t(rhs)); \
} \
\
/* \brief Bitwise and assignment operator. */ \
inline lhs_t & operator&=(lhs_t &lhs, ths_t rhs) noexcept \
{ \
lhs = static_cast<lhs_t>(int_t(lhs) & int_t(rhs)); \
return lhs; \
} \
\
/* \brief Bitwise xor operator. */ \
inline lhs_t operator^(lhs_t lhs, ths_t rhs) noexcept \
{ \
return static_cast<lhs_t>(int_t(lhs) ^ int_t(rhs)); \
} \
\
/* \brief Bitwise xor assignment operator. */ \
inline lhs_t & operator^=(lhs_t &lhs, ths_t rhs) noexcept \
{ \
lhs = static_cast<lhs_t>(int_t(lhs) ^ int_t(rhs)); \
return lhs; \
}
/**
* \brief Set enumeration flags within the same enum.
*/
#define ENUM_FLAG1(enum_t) \
ENUM_FLAG2(enum_t, enum_t) \
\
/* \brief Bitwise negation operator. */ \
inline enum_t operator~(enum_t value) noexcept \
{ \
return static_cast<enum_t>(~int_t(value)); \
} \
\
/* \brief Negation operator. */ \
inline bool operator!(enum_t value) noexcept \
{ \
return int_t(value) == 0; \
}
/**
* \brief Macros to grab the proper bit-wise flag setter.
* `ENUM_ID` is required for MSVC compatibility, since MSVC
* has issues in expanding `__VA_ARGS__` for the dispatcher.
* Don't remove it, even if the above code works without it
* for GCC and Clang.
*/
#define ENUM_ID(x) x
#define GET_ENUM_FLAG(_1,_2,NAME,...) NAME
#define ENUM_FLAG(...) ENUM_ID(GET_ENUM_FLAG(__VA_ARGS__, ENUM_FLAG2, ENUM_FLAG1)(__VA_ARGS__))
15.01.2018
Q_DECLARE_FLAGS(Options, Option)
, почему единственное и множественное число дляOption
? 16.01.2018QFlags<T>
). ЗатемQ_DECLARE_OPERATORS_FOR_FLAGS
экспортирует все операторы в глобальную область. Вы можете немного опустить это, но я в основном использовал свой собственный макрос, а затем регистрировал его в объектной системе Qt в своем собственном коде. Оба работают, мне просто больше нравятся перечисления с областью видимости С++ 11, чем перечисления области видимости Qt. 16.01.2018