1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <QtCore/qglobal.h>
41
42#ifndef QFLAGS_H
43#define QFLAGS_H
44
45#include <initializer_list>
46
47QT_BEGIN_NAMESPACE
48
49class QDataStream;
50
51class QFlag
52{
53 int i;
54public:
55 constexpr inline Q_IMPLICIT QFlag(int value) noexcept : i(value) {}
56 constexpr inline Q_IMPLICIT operator int() const noexcept { return i; }
57
58#if !defined(Q_CC_MSVC)
59 // Microsoft Visual Studio has buggy behavior when it comes to
60 // unsigned enums: even if the enum is unsigned, the enum tags are
61 // always signed
62# if !defined(__LP64__) && !defined(Q_CLANG_QDOC)
63 constexpr inline Q_IMPLICIT QFlag(long value) noexcept : i(int(value)) {}
64 constexpr inline Q_IMPLICIT QFlag(ulong value) noexcept : i(int(long(value))) {}
65# endif
66 constexpr inline Q_IMPLICIT QFlag(uint value) noexcept : i(int(value)) {}
67 constexpr inline Q_IMPLICIT QFlag(short value) noexcept : i(int(value)) {}
68 constexpr inline Q_IMPLICIT QFlag(ushort value) noexcept : i(int(uint(value))) {}
69 constexpr inline Q_IMPLICIT operator uint() const noexcept { return uint(i); }
70#endif
71};
72Q_DECLARE_TYPEINFO(QFlag, Q_PRIMITIVE_TYPE);
73
74class QIncompatibleFlag
75{
76 int i;
77public:
78 constexpr inline explicit QIncompatibleFlag(int i) noexcept;
79 constexpr inline Q_IMPLICIT operator int() const noexcept { return i; }
80};
81Q_DECLARE_TYPEINFO(QIncompatibleFlag, Q_PRIMITIVE_TYPE);
82
83constexpr inline QIncompatibleFlag::QIncompatibleFlag(int value) noexcept : i(value) {}
84
85
86template<typename Enum>
87class QFlags
88{
89 static_assert((sizeof(Enum) <= sizeof(int)),
90 "QFlags uses an int as storage, so an enum with underlying "
91 "long long will overflow.");
92 static_assert((std::is_enum<Enum>::value), "QFlags is only usable on enumeration types.");
93
94public:
95#if defined(Q_CC_MSVC) || defined(Q_CLANG_QDOC)
96 // see above for MSVC
97 // the definition below is too complex for qdoc
98 typedef int Int;
99#else
100 typedef typename std::conditional<
101 std::is_unsigned<typename std::underlying_type<Enum>::type>::value,
102 unsigned int,
103 signed int
104 >::type Int;
105#endif
106 typedef Enum enum_type;
107 // compiler-generated copy/move ctor/assignment operators are fine!
108 constexpr inline QFlags() noexcept : i(0) {}
109 constexpr inline Q_IMPLICIT QFlags(Enum flags) noexcept : i(Int(flags)) {}
110 constexpr inline Q_IMPLICIT QFlags(QFlag flag) noexcept : i(flag) {}
111
112 constexpr inline QFlags(std::initializer_list<Enum> flags) noexcept
113 : i(initializer_list_helper(flags.begin(), flags.end())) {}
114
115 constexpr static inline QFlags fromInt(Int i) noexcept { return QFlags(QFlag(i)); }
116 constexpr inline Int toInt() const noexcept { return i; }
117
118 constexpr inline QFlags &operator&=(int mask) noexcept { i &= mask; return *this; }
119 constexpr inline QFlags &operator&=(uint mask) noexcept { i &= mask; return *this; }
120 constexpr inline QFlags &operator&=(QFlags mask) noexcept { i &= mask.i; return *this; }
121 constexpr inline QFlags &operator&=(Enum mask) noexcept { i &= Int(mask); return *this; }
122 constexpr inline QFlags &operator|=(QFlags other) noexcept { i |= other.i; return *this; }
123 constexpr inline QFlags &operator|=(Enum other) noexcept { i |= Int(other); return *this; }
124 constexpr inline QFlags &operator^=(QFlags other) noexcept { i ^= other.i; return *this; }
125 constexpr inline QFlags &operator^=(Enum other) noexcept { i ^= Int(other); return *this; }
126
127 constexpr inline operator Int() const noexcept { return i; }
128
129 constexpr inline QFlags operator|(QFlags other) const noexcept { return QFlags(QFlag(i | other.i)); }
130 constexpr inline QFlags operator|(Enum other) const noexcept { return QFlags(QFlag(i | Int(other))); }
131 constexpr inline QFlags operator^(QFlags other) const noexcept { return QFlags(QFlag(i ^ other.i)); }
132 constexpr inline QFlags operator^(Enum other) const noexcept { return QFlags(QFlag(i ^ Int(other))); }
133 constexpr inline QFlags operator&(int mask) const noexcept { return QFlags(QFlag(i & mask)); }
134 constexpr inline QFlags operator&(uint mask) const noexcept { return QFlags(QFlag(i & mask)); }
135 constexpr inline QFlags operator&(QFlags other) const noexcept { return QFlags(QFlag(i & other.i)); }
136 constexpr inline QFlags operator&(Enum other) const noexcept { return QFlags(QFlag(i & Int(other))); }
137 constexpr inline QFlags operator~() const noexcept { return QFlags(QFlag(~i)); }
138
139 constexpr inline void operator+(QFlags other) const noexcept = delete;
140 constexpr inline void operator+(Enum other) const noexcept = delete;
141 constexpr inline void operator+(int other) const noexcept = delete;
142 constexpr inline void operator-(QFlags other) const noexcept = delete;
143 constexpr inline void operator-(Enum other) const noexcept = delete;
144 constexpr inline void operator-(int other) const noexcept = delete;
145
146 constexpr inline bool operator!() const noexcept { return !i; }
147
148 constexpr inline bool testFlag(Enum flag) const noexcept { return testFlags(flag); }
149 constexpr inline bool testFlags(QFlags flags) const noexcept { return flags.i ? ((i & flags.i) == flags.i) : i == Int(0); }
150 constexpr inline bool testAnyFlag(Enum flag) const noexcept { return testAnyFlags(flag); }
151 constexpr inline bool testAnyFlags(QFlags flags) const noexcept { return (i & flags.i) != Int(0); }
152 constexpr inline QFlags &setFlag(Enum flag, bool on = true) noexcept
153 {
154 return on ? (*this |= flag) : (*this &= ~QFlags(flag));
155 }
156
157 friend constexpr inline bool operator==(QFlags lhs, QFlags rhs) noexcept
158 { return lhs.i == rhs.i; }
159 friend constexpr inline bool operator!=(QFlags lhs, QFlags rhs) noexcept
160 { return lhs.i != rhs.i; }
161 friend constexpr inline bool operator==(QFlags lhs, Enum rhs) noexcept
162 { return lhs == QFlags(rhs); }
163 friend constexpr inline bool operator!=(QFlags lhs, Enum rhs) noexcept
164 { return lhs != QFlags(rhs); }
165 friend constexpr inline bool operator==(Enum lhs, QFlags rhs) noexcept
166 { return QFlags(lhs) == rhs; }
167 friend constexpr inline bool operator!=(Enum lhs, QFlags rhs) noexcept
168 { return QFlags(lhs) != rhs; }
169
170private:
171 constexpr static inline Int initializer_list_helper(typename std::initializer_list<Enum>::const_iterator it,
172 typename std::initializer_list<Enum>::const_iterator end)
173 noexcept
174 {
175 return (it == end ? Int(0) : (Int(*it) | initializer_list_helper(it + 1, end)));
176 }
177
178 Int i;
179};
180
181#ifndef Q_MOC_RUN
182#define Q_DECLARE_FLAGS(Flags, Enum)\
183typedef QFlags<Enum> Flags;
184#endif
185
186#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
187constexpr inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept \
188{ return QFlags<Flags::enum_type>(f1) | f2; } \
189constexpr inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
190{ return f2 | f1; } \
191constexpr inline QFlags<Flags::enum_type> operator&(Flags::enum_type f1, Flags::enum_type f2) noexcept \
192{ return QFlags<Flags::enum_type>(f1) & f2; } \
193constexpr inline QFlags<Flags::enum_type> operator&(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
194{ return f2 & f1; } \
195constexpr inline void operator+(Flags::enum_type f1, Flags::enum_type f2) noexcept = delete; \
196constexpr inline void operator+(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
197constexpr inline void operator+(int f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
198constexpr inline void operator-(Flags::enum_type f1, Flags::enum_type f2) noexcept = delete; \
199constexpr inline void operator-(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
200constexpr inline void operator-(int f1, QFlags<Flags::enum_type> f2) noexcept = delete; \
201constexpr inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) noexcept \
202{ return QIncompatibleFlag(int(f1) | f2); } \
203constexpr inline void operator+(int f1, Flags::enum_type f2) noexcept = delete; \
204constexpr inline void operator+(Flags::enum_type f1, int f2) noexcept = delete; \
205constexpr inline void operator-(int f1, Flags::enum_type f2) noexcept = delete; \
206constexpr inline void operator-(Flags::enum_type f1, int f2) noexcept = delete;
207
208QT_END_NAMESPACE
209
210#endif // QFLAGS_H
211

source code of qtbase/src/corelib/global/qflags.h