(1)本文所有内容来自于头文件 qflags.h ,整合了官方的注释:
//The QFlag class is a helper data type for QFlags.
//它等同于一个普通的int,除了函数重载和类型转换方面。
//你永远不需要在你的应用程序中使用这个类。
//It is equivalent to a plain int,
//except with respect to function overloading and type conversions.
//You should never need to use this class in your applications.
class QFlag
{
int i;
public:
constexpr inline Q_IMPLICIT //本类的构造函数
QFlag(int value) noexcept : i(value) {}
//说明本类可自动转换为 int 类型,枚举类的本质,其实还是 int 类型
constexpr inline Q_IMPLICIT //类型转换运算符函数
operator int() const noexcept { return i; }
#if !defined(Q_CC_MSVC) //经验证,本 QT 确实没有定义此宏 Q_CC_MSVC。本 #if有效
// Microsoft Visual Studio has buggy有小错的 behavior
// when it comes to unsigned enums:
// even if the enum is unsigned, the enum tags are always signed
//当涉及到无符号枚举时,Microsoft VisualStudio有错误的行为:
//即使枚举是未签名的,枚举标记始终是签名的
# if !defined(__LP64__) && !defined(Q_CLANG_QDOC) //彩色,有效
constexpr inline Q_IMPLICIT QFlag( long value) noexcept
: i(int(value)) {} // 依然是构造函数
constexpr inline Q_IMPLICIT QFlag(ulong value) noexcept
: i(int(long(value))) {}
# endif
constexpr inline Q_IMPLICIT QFlag(uint value) noexcept
: i(int(value)) {} //这里其实是构成了构造函数的重载
constexpr inline Q_IMPLICIT QFlag(short value) noexcept
: i(int(value)) {}
constexpr inline Q_IMPLICIT QFlag(ushort value) noexcept
: i(int(uint(value))) {}
constexpr inline Q_IMPLICIT operator uint() const noexcept
{ return uint(i); } //类型转换运算符函数,转换为无符号 int
#endif // #if !defined(Q_CC_MSVC)
}; //此宏是为了描述本新类型的存储特性
Q_DECLARE_TYPEINFO(QFlag, Q_PRIMITIVE_TYPE);
/* 相当于为模板类型 QTypeInfo 特化出了一个具体类型,描述本 QFlag 的存储特性
template<>
class QTypeInfo<QFlag> //Q_PRIMITIVE_TYPE 用于实例化本新类型中的数据成员
*/
(2)宏定义 Q_DECLARE_TYPEINFO(TYPE, FLAGS) :
/*
Specialize a specific type with:
Q_DECLARE_TYPEINFO(type, flags);
where 'type' is the name of the type to specialize and 'flags' is
logically-OR'ed combination of the flags below.
*/
/* TYPEINFO flags */
enum {
Q_COMPLEX_TYPE = 0,
Q_PRIMITIVE_TYPE = 0x1,
Q_RELOCATABLE_TYPE = 0x2,
Q_MOVABLE_TYPE = 0x2,
Q_DUMMY_TYPE = 0x4,
};
#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \
class QTypeInfo<TYPE > \
{ \
public: \
enum { \
isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && !std::is_trivial_v<TYPE>, \
isRelocatable = !isComplex || ((FLAGS) & Q_RELOCATABLE_TYPE) || qIsRelocatable<TYPE>, \
isPointer = false, \
isIntegral = std::is_integral< TYPE >::value, \
}; \
}
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
template<> \
Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
(3)Qt 里重要地方基础类 QFlags ,其支持了对枚举量的或运算:
//统计本标志类支持的运算符: &= |= ^= != ==复合, & | ^ ~ 单目,禁止 + -
template<typename Enum> //模板参数 Enum 是枚举类型
class QFlags
{
//此静态断言是要求本模板类中的模板参数的类型的大小不可以超过 int
static_assert((sizeof(Enum) <= sizeof(int)),
"QFlags uses an int as storage, so an enum with underlying "
"long long will overflow.");
/* // is_enum
template<typename _Tp> 可见所谓枚举类型就是要求必须是整数类型
struct is_enum : public integral_constant<bool, __is_enum(_Tp)> { };
*/
static_assert((std::is_enum<Enum>::value),
"QFlags is only usable on enumeration types.");
private:
constexpr static inline
Int initializer_list_helper( //静态的私有成员函数
typename std::initializer_list<Enum>::const_iterator it,
typename std::initializer_list<Enum>::const_iterator end) noexcept
{
return (it == end ?
Int(0) :
( Int(*it) | initializer_list_helper(it + 1, end) )
);
}
Int i; //此 Int 的定义在下面。定义了本类的数据成员,存储了一个整形数值
public:
#if defined(Q_CC_MSVC) || defined(Q_CLANG_QDOC)
// see above for MSVC
// the definition below is too complex for qdoc
typedef int Int;
#else // 此 else 是有效的
typedef typename std::conditional< //又是 conditional
std::is_unsigned<typename std::underlying_type<Enum>::type>::value,
unsigned int,
signed int
>::type Int;
#endif
typedef Enum enum_type; //对模板参数做了重命名
// compiler-generated copy/move ctor/assignment operators are fine!
constexpr inline QFlags() noexcept : i(0) {} //默认构造函数
constexpr inline Q_IMPLICIT QFlags(Enum flags) noexcept
: i(Int(flags)) {} //有参构造函数
constexpr inline Q_IMPLICIT QFlags(QFlag flag) noexcept :
i(flag) {} //class QFlag { int i; }
constexpr inline QFlags(std::initializer_list<Enum> flags) noexcept
: i(initializer_list_helper(flags.begin(), flags.end())) {}
//本静态成员函数根据形参的整数 i 构造并返回一个本 QFlags 对象
constexpr static inline QFlags fromInt(Int i) noexcept
{ return QFlags(QFlag(i)); }
//把本类型的值转化为整数返回
constexpr inline Int toInt() const noexcept { return i; }
//类型转换函数
constexpr inline operator Int() const noexcept { return i; }
constexpr inline bool operator!() const noexcept { return !i; }
constexpr inline QFlags & operator&=(int mask) noexcept
{ i &= mask ; return *this; } //运算符函数 &= 与等于
constexpr inline QFlags & operator&=(uint mask) noexcept
{ i &= mask ; return *this; } //运算符函数 &= 重载
constexpr inline QFlags & operator&=(QFlags mask) noexcept
{ i &= mask.i ; return *this; } //运算符函数 &= 重载
constexpr inline QFlags & operator&=(Enum mask) noexcept
{ i &= Int(mask); return *this; } //运算符函数 &= 重载
constexpr inline QFlags & operator|=(QFlags other) noexcept
{ i |= other.i ; return *this; } //运算符函数 |= 或等于
constexpr inline QFlags &operator|=(Enum other) noexcept
{ i |= Int(other); return *this; } //运算符函数 |= 重载
constexpr inline QFlags &operator^=(QFlags other) noexcept
{ i ^= other.i ; return *this; } //运算符函数 ^= 异或等于
constexpr inline QFlags &operator^=(Enum other) noexcept
{ i ^= Int(other); return *this; } //运算符函数 ^= 重载
friend constexpr inline bool operator==(QFlags lhs, QFlags rhs) noexcept
{ return lhs.i == rhs.i; }
friend constexpr inline bool operator==(QFlags lhs, Enum rhs) noexcept
{ return lhs == QFlags(rhs); }
friend constexpr inline bool operator==(Enum lhs, QFlags rhs) noexcept
{ return QFlags(lhs) == rhs; }
friend constexpr inline bool operator!=(QFlags lhs, QFlags rhs) noexcept
{ return lhs.i != rhs.i; }
friend constexpr inline bool operator!=(QFlags lhs, Enum rhs) noexcept
{ return lhs != QFlags(rhs); }
friend constexpr inline bool operator!=(Enum lhs, QFlags rhs) noexcept
{ return QFlags(lhs) != rhs; }
constexpr inline QFlags operator|(QFlags other) const noexcept
{ return QFlags(QFlag(i | other.i)); } //定义了运算符 | 按位或
constexpr inline QFlags operator|(Enum other) const noexcept
{ return QFlags(QFlag(i | Int(other))); }
constexpr inline QFlags operator^(QFlags other) const noexcept
{ return QFlags(QFlag(i ^ other.i)); } //定义了运算符 ^ 异或
constexpr inline QFlags operator^(Enum other) const noexcept
{ return QFlags(QFlag(i ^ Int(other))); }
constexpr inline QFlags operator&(int mask) const noexcept
{ return QFlags(QFlag(i & mask)); } //定义了运算符 & 与
constexpr inline QFlags operator&(uint mask) const noexcept
{ return QFlags(QFlag(i & mask)); }
constexpr inline QFlags operator&(QFlags other) const noexcept
{ return QFlags(QFlag(i & other.i)); }
constexpr inline QFlags operator&(Enum other) const noexcept
{ return QFlags(QFlag(i & Int(other))); }
constexpr inline QFlags operator~() const noexcept
{ return QFlags(QFlag(~i)); } //定义了运算符 ~ 取反
constexpr inline void operator+(QFlags other) const noexcept = delete;
constexpr inline void operator+(Enum other) const noexcept = delete;
constexpr inline void operator+(int other) const noexcept = delete;
constexpr inline void operator-(QFlags other) const noexcept = delete;
constexpr inline void operator-(Enum other) const noexcept = delete;
constexpr inline void operator-(int other) const noexcept = delete;
constexpr inline bool testFlags(QFlags flags) const noexcept
{ return flags.i
? ((i & flags.i) == flags.i)
: i == Int(0);
}
constexpr inline bool testFlag(Enum flag) const noexcept
{ return testFlags(flag); }
constexpr inline bool testAnyFlags(QFlags flags) const noexcept
{ return (i & flags.i) != Int(0); }
constexpr inline bool testAnyFlag (Enum flag) const noexcept
{ return testAnyFlags(flag); }
constexpr inline QFlags & setFlag(Enum flag, bool on = true) noexcept
{ //形参 true则添加标志 , false 则去掉标志
return on ? (*this |= flag) : (*this &= ~QFlags(flag));
}
}; //class QFlags
(4)两个重要的宏的定义 Q_DECLARE_FLAGS(Flags, Enum),以及 Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) :
#ifndef Q_MOC_RUN
#define Q_DECLARE_FLAGS(Flags, Enum)\
typedef QFlags<Enum> Flags;
#endif
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
constexpr inline QFlags<Flags::enum_type> operator| \
(Flags::enum_type f1, Flags::enum_type f2) noexcept \
{ return QFlags<Flags::enum_type>(f1) | f2; } \
\
constexpr inline QFlags<Flags::enum_type> operator| \
(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
{ return f2 | f1; } \
\
constexpr inline QFlags<Flags::enum_type> operator& \
(Flags::enum_type f1, Flags::enum_type f2) noexcept \
{ return QFlags<Flags::enum_type>(f1) & f2; } \
\
constexpr inline QFlags<Flags::enum_type> operator& \
(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
{ return f2 & f1; } \
\
constexpr inline \
void operator+(Flags::enum_type f1,Flags::enum_type f2) noexcept = delete; \
\
constexpr inline \
void operator+(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
\
constexpr inline \
void operator+(int f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
\
constexpr inline \
void operator-(Flags::enum_type f1, Flags::enum_type f2) noexcept = delete; \
\
constexpr inline \
void operator-(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
\
constexpr inline \
void operator-(int f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
\
constexpr inline \
QIncompatibleFlag operator|(Flags::enum_type f1, int f2) noexcept \
{ return QIncompatibleFlag(int(f1) | f2); } \
\
constexpr inline void operator+(int f1, Flags::enum_type f2) noexcept = delete; \
constexpr inline void operator+(Flags::enum_type f1, int f2) noexcept = delete; \
constexpr inline void operator-(int f1, Flags::enum_type f2) noexcept = delete; \
constexpr inline void operator-(Flags::enum_type f1, int f2) noexcept = delete;
(5)
谢谢