File indexing completed on 2025-09-17 09:09:16
0001
0002
0003
0004 #ifndef QFLAGS_H
0005 #define QFLAGS_H
0006
0007 #include <QtCore/qcompare_impl.h>
0008 #include <QtCore/qtypeinfo.h>
0009
0010 #include <algorithm>
0011 #include <initializer_list>
0012
0013 QT_BEGIN_NAMESPACE
0014
0015 template<typename Enum> class QFlags;
0016
0017 class QFlag
0018 {
0019 int i;
0020 public:
0021 constexpr inline Q_IMPLICIT QFlag(int value) noexcept : i(value) {}
0022 constexpr inline Q_IMPLICIT operator int() const noexcept { return i; }
0023
0024 #if !defined(Q_CC_MSVC)
0025
0026
0027
0028 # if !defined(__LP64__) && !defined(Q_QDOC)
0029 constexpr inline Q_IMPLICIT QFlag(long value) noexcept : i(int(value)) {}
0030 constexpr inline Q_IMPLICIT QFlag(ulong value) noexcept : i(int(long(value))) {}
0031 # endif
0032 constexpr inline Q_IMPLICIT QFlag(uint value) noexcept : i(int(value)) {}
0033 constexpr inline Q_IMPLICIT QFlag(short value) noexcept : i(int(value)) {}
0034 constexpr inline Q_IMPLICIT QFlag(ushort value) noexcept : i(int(uint(value))) {}
0035 constexpr inline Q_IMPLICIT operator uint() const noexcept { return uint(i); }
0036 #endif
0037 };
0038 Q_DECLARE_TYPEINFO(QFlag, Q_PRIMITIVE_TYPE);
0039
0040 class QIncompatibleFlag
0041 {
0042 int i;
0043 public:
0044 constexpr inline explicit QIncompatibleFlag(int i) noexcept;
0045 constexpr inline Q_IMPLICIT operator int() const noexcept { return i; }
0046 };
0047 Q_DECLARE_TYPEINFO(QIncompatibleFlag, Q_PRIMITIVE_TYPE);
0048
0049 constexpr inline QIncompatibleFlag::QIncompatibleFlag(int value) noexcept : i(value) {}
0050
0051 namespace QtPrivate {
0052 template <typename T> struct IsQFlags : std::false_type {};
0053 template <typename E> struct IsQFlags<QFlags<E>> : std::true_type {};
0054
0055 template<typename Enum>
0056 class QFlagsStorage
0057 {
0058 static_assert(sizeof(Enum) <= sizeof(quint64),
0059 "Only enumerations 64 bits or smaller are supported.");
0060 static_assert((std::is_enum<Enum>::value), "QFlags is only usable on enumeration types.");
0061
0062 static constexpr size_t IntegerSize = (std::max)(sizeof(Enum), sizeof(int));
0063 using Integers = QIntegerForSize<IntegerSize>;
0064
0065 protected:
0066 typedef typename std::conditional<
0067 std::is_unsigned<typename std::underlying_type<Enum>::type>::value,
0068 typename Integers::Unsigned,
0069 typename Integers::Signed
0070 >::type Int;
0071
0072 Int i = 0;
0073
0074 QT_DECLARE_RO5_SMF_AS_DEFAULTED(QFlagsStorage)
0075 public:
0076 constexpr inline QFlagsStorage() noexcept = default;
0077 constexpr inline explicit QFlagsStorage(std::in_place_t, Int v) : i(v) {}
0078 };
0079
0080 template <typename Enum, int Size = sizeof(QFlagsStorage<Enum>)>
0081 struct QFlagsStorageHelper : QFlagsStorage<Enum>
0082 {
0083 using QFlagsStorage<Enum>::QFlagsStorage;
0084 protected:
0085 QT_DECLARE_RO5_SMF_AS_DEFAULTED(QFlagsStorageHelper)
0086 };
0087 template <typename Enum> struct QFlagsStorageHelper<Enum, sizeof(int)> : QFlagsStorage<Enum>
0088 {
0089 using QFlagsStorage<Enum>::QFlagsStorage;
0090
0091
0092
0093
0094
0095 constexpr inline Q_IMPLICIT QFlagsStorageHelper(QFlag flag) noexcept
0096 : QFlagsStorage<Enum>(std::in_place, flag) {}
0097 #ifdef QT_TYPESAFE_FLAGS
0098 constexpr inline explicit operator QFlag() const noexcept { return QFlag(this->i); }
0099 #endif
0100 protected:
0101 QT_DECLARE_RO5_SMF_AS_DEFAULTED(QFlagsStorageHelper)
0102 };
0103 }
0104
0105 template<typename Enum>
0106 class QFlags : public QtPrivate::QFlagsStorageHelper<Enum>
0107 {
0108 using Base = QtPrivate::QFlagsStorageHelper<Enum>;
0109 public:
0110 typedef Enum enum_type;
0111 using Int = typename Base::Int;
0112 using Base::Base;
0113
0114
0115 constexpr inline QFlags() noexcept = default;
0116
0117 constexpr inline Q_IMPLICIT QFlags(Enum flags) noexcept : Base(std::in_place, Int(flags)) {}
0118
0119 #ifdef Q_QDOC
0120 constexpr inline Q_IMPLICIT QFlags(std::in_place_t, Int flags) noexcept;
0121 constexpr inline Q_IMPLICIT QFlags(QFlag flag) noexcept
0122 requires(sizeof(Enum) == sizeof(int));
0123 #endif
0124
0125 constexpr inline QFlags(std::initializer_list<Enum> flags) noexcept
0126 : Base(std::in_place, initializer_list_helper(flags.begin(), flags.end())) {}
0127
0128 constexpr static inline QFlags fromInt(Int i) noexcept { return QFlags(std::in_place, i); }
0129 constexpr inline Int toInt() const noexcept { return i; }
0130
0131 #ifndef QT_TYPESAFE_FLAGS
0132 constexpr inline QFlags &operator&=(int mask) noexcept { i &= mask; return *this; }
0133 constexpr inline QFlags &operator&=(uint mask) noexcept { i &= mask; return *this; }
0134 #endif
0135 constexpr inline QFlags &operator&=(QFlags mask) noexcept { i &= mask.i; return *this; }
0136 constexpr inline QFlags &operator&=(Enum mask) noexcept { i &= Int(mask); return *this; }
0137 constexpr inline QFlags &operator|=(QFlags other) noexcept { i |= other.i; return *this; }
0138 constexpr inline QFlags &operator|=(Enum other) noexcept { i |= Int(other); return *this; }
0139 constexpr inline QFlags &operator^=(QFlags other) noexcept { i ^= other.i; return *this; }
0140 constexpr inline QFlags &operator^=(Enum other) noexcept { i ^= Int(other); return *this; }
0141
0142 #ifdef QT_TYPESAFE_FLAGS
0143 constexpr inline explicit operator Int() const noexcept { return i; }
0144 constexpr inline explicit operator bool() const noexcept { return i; }
0145 #else
0146 constexpr inline Q_IMPLICIT operator Int() const noexcept { return i; }
0147 constexpr inline bool operator!() const noexcept { return !i; }
0148 #endif
0149
0150 constexpr inline QFlags operator|(QFlags other) const noexcept { return QFlags(std::in_place, i | other.i); }
0151 constexpr inline QFlags operator|(Enum other) const noexcept { return QFlags(std::in_place, i | Int(other)); }
0152 constexpr inline QFlags operator^(QFlags other) const noexcept { return QFlags(std::in_place, i ^ other.i); }
0153 constexpr inline QFlags operator^(Enum other) const noexcept { return QFlags(std::in_place, i ^ Int(other)); }
0154 #ifndef QT_TYPESAFE_FLAGS
0155 constexpr inline QFlags operator&(int mask) const noexcept { return QFlags(std::in_place, i & mask); }
0156 constexpr inline QFlags operator&(uint mask) const noexcept { return QFlags(std::in_place, i & mask); }
0157 #endif
0158 constexpr inline QFlags operator&(QFlags other) const noexcept { return QFlags(std::in_place, i & other.i); }
0159 constexpr inline QFlags operator&(Enum other) const noexcept { return QFlags(std::in_place, i & Int(other)); }
0160 constexpr inline QFlags operator~() const noexcept { return QFlags(std::in_place, ~i); }
0161
0162 constexpr inline void operator+(QFlags other) const noexcept = delete;
0163 constexpr inline void operator+(Enum other) const noexcept = delete;
0164 constexpr inline void operator+(int other) const noexcept = delete;
0165 constexpr inline void operator-(QFlags other) const noexcept = delete;
0166 constexpr inline void operator-(Enum other) const noexcept = delete;
0167 constexpr inline void operator-(int other) const noexcept = delete;
0168
0169 constexpr inline bool testFlag(Enum flag) const noexcept { return testFlags(flag); }
0170 constexpr inline bool testFlags(QFlags flags) const noexcept { return flags.i ? ((i & flags.i) == flags.i) : i == Int(0); }
0171 constexpr inline bool testAnyFlag(Enum flag) const noexcept { return testAnyFlags(flag); }
0172 constexpr inline bool testAnyFlags(QFlags flags) const noexcept { return (i & flags.i) != Int(0); }
0173 constexpr inline QFlags &setFlag(Enum flag, bool on = true) noexcept
0174 {
0175 return on ? (*this |= flag) : (*this &= ~QFlags(flag));
0176 }
0177
0178 friend constexpr inline bool operator==(QFlags lhs, QFlags rhs) noexcept
0179 { return lhs.i == rhs.i; }
0180 friend constexpr inline bool operator!=(QFlags lhs, QFlags rhs) noexcept
0181 { return lhs.i != rhs.i; }
0182 friend constexpr inline bool operator==(QFlags lhs, Enum rhs) noexcept
0183 { return lhs == QFlags(rhs); }
0184 friend constexpr inline bool operator!=(QFlags lhs, Enum rhs) noexcept
0185 { return lhs != QFlags(rhs); }
0186 friend constexpr inline bool operator==(Enum lhs, QFlags rhs) noexcept
0187 { return QFlags(lhs) == rhs; }
0188 friend constexpr inline bool operator!=(Enum lhs, QFlags rhs) noexcept
0189 { return QFlags(lhs) != rhs; }
0190
0191 #ifdef QT_TYPESAFE_FLAGS
0192
0193
0194
0195 friend constexpr inline bool operator==(QFlags flags, QtPrivate::CompareAgainstLiteralZero) noexcept
0196 { return flags.i == Int(0); }
0197 friend constexpr inline bool operator!=(QFlags flags, QtPrivate::CompareAgainstLiteralZero) noexcept
0198 { return flags.i != Int(0); }
0199 friend constexpr inline bool operator==(QtPrivate::CompareAgainstLiteralZero, QFlags flags) noexcept
0200 { return Int(0) == flags.i; }
0201 friend constexpr inline bool operator!=(QtPrivate::CompareAgainstLiteralZero, QFlags flags) noexcept
0202 { return Int(0) != flags.i; }
0203 #endif
0204
0205 private:
0206 constexpr static inline Int initializer_list_helper(typename std::initializer_list<Enum>::const_iterator it,
0207 typename std::initializer_list<Enum>::const_iterator end)
0208 noexcept
0209 {
0210 return (it == end ? Int(0) : (Int(*it) | initializer_list_helper(it + 1, end)));
0211 }
0212
0213 using Base::i;
0214 };
0215
0216 #ifndef Q_MOC_RUN
0217 #define Q_DECLARE_FLAGS(Flags, Enum)\
0218 typedef QFlags<Enum> Flags;
0219 #endif
0220
0221 #ifdef QT_TYPESAFE_FLAGS
0222
0223
0224 #define QT_DECLARE_TYPESAFE_OPERATORS_FOR_FLAGS_ENUM(Flags) \
0225 [[maybe_unused]] \
0226 constexpr inline Flags operator~(Flags::enum_type e) noexcept \
0227 { return ~Flags(e); } \
0228 [[maybe_unused]] \
0229 constexpr inline void operator|(Flags::enum_type f1, int f2) noexcept = delete;
0230 #else
0231 #define QT_DECLARE_TYPESAFE_OPERATORS_FOR_FLAGS_ENUM(Flags) \
0232 [[maybe_unused]] \
0233 constexpr inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) noexcept \
0234 { return QIncompatibleFlag(int(f1) | f2); }
0235 #endif
0236
0237 #define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
0238 [[maybe_unused]] \
0239 constexpr inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept \
0240 { return QFlags<Flags::enum_type>(f1) | f2; } \
0241 [[maybe_unused]] \
0242 constexpr inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
0243 { return f2 | f1; } \
0244 [[maybe_unused]] \
0245 constexpr inline QFlags<Flags::enum_type> operator&(Flags::enum_type f1, Flags::enum_type f2) noexcept \
0246 { return QFlags<Flags::enum_type>(f1) & f2; } \
0247 [[maybe_unused]] \
0248 constexpr inline QFlags<Flags::enum_type> operator&(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
0249 { return f2 & f1; } \
0250 [[maybe_unused]] \
0251 constexpr inline QFlags<Flags::enum_type> operator^(Flags::enum_type f1, Flags::enum_type f2) noexcept \
0252 { return QFlags<Flags::enum_type>(f1) ^ f2; } \
0253 [[maybe_unused]] \
0254 constexpr inline QFlags<Flags::enum_type> operator^(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
0255 { return f2 ^ f1; } \
0256 constexpr inline void operator+(Flags::enum_type f1, Flags::enum_type f2) noexcept = delete; \
0257 constexpr inline void operator+(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
0258 constexpr inline void operator+(int f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
0259 constexpr inline void operator-(Flags::enum_type f1, Flags::enum_type f2) noexcept = delete; \
0260 constexpr inline void operator-(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
0261 constexpr inline void operator-(int f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
0262 constexpr inline void operator+(int f1, Flags::enum_type f2) noexcept = delete; \
0263 constexpr inline void operator+(Flags::enum_type f1, int f2) noexcept = delete; \
0264 constexpr inline void operator-(int f1, Flags::enum_type f2) noexcept = delete; \
0265 constexpr inline void operator-(Flags::enum_type f1, int f2) noexcept = delete; \
0266 QT_DECLARE_TYPESAFE_OPERATORS_FOR_FLAGS_ENUM(Flags)
0267
0268
0269
0270 #if __cplusplus > 201702L
0271
0272 # define Q_DECLARE_MIXED_ENUM_OPERATOR(op, Ret, LHS, RHS) \
0273 [[maybe_unused]] \
0274 constexpr inline Ret operator op (LHS lhs, RHS rhs) noexcept \
0275 { return static_cast<Ret>(qToUnderlying(lhs) op qToUnderlying(rhs)); } \
0276
0277 #else
0278
0279
0280 # define Q_DECLARE_MIXED_ENUM_OPERATOR(op, Ret, LHS, RHS) \
0281 static_assert(std::is_same_v<decltype(std::declval<LHS>() op std::declval<RHS>()), Ret>);
0282 #endif
0283
0284 #define Q_DECLARE_MIXED_ENUM_OPERATORS(Ret, Flags, Enum) \
0285 Q_DECLARE_MIXED_ENUM_OPERATOR(|, Ret, Flags, Enum) \
0286 Q_DECLARE_MIXED_ENUM_OPERATOR(&, Ret, Flags, Enum) \
0287 Q_DECLARE_MIXED_ENUM_OPERATOR(^, Ret, Flags, Enum) \
0288
0289
0290 #define Q_DECLARE_MIXED_ENUM_OPERATORS_SYMMETRIC(Ret, Flags, Enum) \
0291 Q_DECLARE_MIXED_ENUM_OPERATORS(Ret, Flags, Enum) \
0292 Q_DECLARE_MIXED_ENUM_OPERATORS(Ret, Enum, Flags) \
0293
0294
0295
0296 QT_END_NAMESPACE
0297
0298 #endif