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>
This commit is contained in:
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
Block a user