Q_DECLARE_OPERATORS_FOR_FLAGS: also define operator&
Bitwise ANDing an enum and a QFlags should yield identical results
as ANDing a QFlags and the enum. This latter operator already existed,
so add support for the former.
Plus, ANDing two enumerators of a flag type should yield a QFlags, and
not a plain int. (Note that an arbitrary amount of bits can be set
in the result of such operation, as the enumerators themselves may be
masks with more than 1 bit set.)
This is slightly source incompatible, as we're changing the return
type of operator&. Code that was assigning that result to `int` still
works as expected, but code that wanted the value back in a QFlags may
have inserted some conversions like:
flag = Enum(enumerator & otherFlag);
^---------------------
used to yield int, now QFlags
which are now going to break as there's no QFlags->Enum conversion.
An earlier attempt of this patch, introduced -- and immediately
deprecated -- such a conversion, under the form of
explicit operator Enum() const;
in order to keep such old code working both before and after this
change. The problem is that MSVC has a bug with explicit conversions to
enumerations [1], which get accidentally considered when they shouldn't,
and thus making a lot of code stop compiling due to (false) ambiguities.
So, I'm not adding that operator any more.
Note that there's a way to keep code working before and after this
change: just use
flag = Flags(enumerator & otherFlag); // Flags, not Enum
(thanks Edward), which goes through a int -> QFlag -> QFlags conversion,
and arguably is the idiomatic way of writing such code; or use
flag = otherFlag & enumerator;
which, as discussed above, has always returned a QFlags.
[1] https://developercommunity2.visualstudio.com/t/explicit-conversion-operator-to-enum-is/1412616
[ChangeLog][Potentially Source-Incompatible Changes][QFlags] Bitwise
AND-ing two values of an enum type for which flag operations have been
declared now produces a QFlags object. Similarly, AND-ing a value
of enum type and one of type QFlags now produces a QFlags object.
Before, it produced an integer in both cases. This may introduce a
slight incompatibility in user code; it is possible to keep the code
working in Qt versions before and after this change by inserting
enough conversions to QFlags, and/or by changing expressions such as
`enum & flag` to `flag & enum` (the latter has always produced a QFlags
object).
Change-Id: I6e645c010d3aa677820545b0c25678f1dc9a3295
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
parent
d2759e0e32
commit
2be9e6cc26
|
|
@ -172,6 +172,10 @@ constexpr inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::
|
|||
{ 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; \
|
||||
|
|
|
|||
Loading…
Reference in New Issue