Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:09:16

0001 // Copyright (C) 2016 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
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     // Microsoft Visual Studio has buggy behavior when it comes to
0026     // unsigned enums: even if the enum is unsigned, the enum tags are
0027     // always signed
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     // For compatibility with Qt 3, moc goes through QFlag in order to
0092     // read/write properties of type QFlags; so a conversion to QFlag is also
0093     // needed here. (It otherwise goes through a QFlags->int->QFlag conversion
0094     // sequence.)
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 } // namespace QtPrivate
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     // compiler-generated copy/move ctor/assignment operators are fine!
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     // Provide means of comparing flags against a literal 0; opt-in
0193     // because otherwise they're ambiguous against operator==(int,int)
0194     // after a QFlags->int conversion.
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 // These are opt-in, for backwards compatibility
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 // restore bit-wise enum-enum operators deprecated in C++20,
0269 // but used in a few places in the API
0270 #if __cplusplus > 201702L // assume compilers don't warn if in C++17 mode
0271   // in C++20 mode, provide user-defined operators to override the deprecated operations:
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     /* end */
0277 #else
0278   // in C++17 mode, statically-assert that this compiler's result of the
0279   // operation is the same that the C++20 version would produce:
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     /* end */
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     /* end */
0294 
0295 
0296 QT_END_NAMESPACE
0297 
0298 #endif // QFLAGS_H