diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2021-05-02 03:06:18 +0200 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2021-06-23 03:14:09 +0200 |
commit | 631a0cc45cbe70940746cd944d325d7d3bab8c15 (patch) | |
tree | 90b375bac817f1999a44f3c37feb193a99ead081 /src/corelib/global/qcompare.h | |
parent | a20a4240668faa0e6c961b90266918628f9f5484 (diff) |
Long live QT_TYPESAFE_FLAGS!
This commit adds an opt-in mechanism to kill type-unsafe functions
and implicit conversions of QFlags, therefore removing an entire
category of bugs that QFlags itself is supposed to protect against:
QFlags<E> f;
f == 3.14; // OK; f->int, int->double, then operator==(double,double)
f & UnrelatedEnum; // OK if of unscoped enum, calls operator&(int)
f &= 123; // calls QFlags::operator&=(int)
int i = f * 42; // f->int, then operator*(int, int)
Thankfully, operator+ and operator- had already been deleted.
By defining QT_TYPESAFE_FLAGS one:
* disables operators taking (u)int, forcing the usage of an enumeration
or another QFlags object;
* turns the implicit conversions towards integers/bool in explicit
(one can always use fromInt/toInt instead);
* adds a convenience set of (in)equality operators against literal 0,
in order to keep code like `(flag & bit) == 0` compile. This set can't
be added normally otherwise it would add ambiguity;
* adds the unary operator~(Enum), turning it into a flag. This is
a source incompatible change, in general, so it's opt-in.
This is a Qt-internal macro at this point. It can't be offered to users
yet because we need to fix some public API flaws first: in some places
(e.g. QPainter::drawText) we ask users to do type-unsafe manipulation
of flags. A user enabling the macro wouldn't be able to properly use the
functions in question.
This macro will be enabled in a follow-up commit.
Change-Id: I796f2256b446bafc12cdcbaf7de417d12bd3619e
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/global/qcompare.h')
-rw-r--r-- | src/corelib/global/qcompare.h | 11 |
1 files changed, 1 insertions, 10 deletions
diff --git a/src/corelib/global/qcompare.h b/src/corelib/global/qcompare.h index 07f4589984..8bc3029c89 100644 --- a/src/corelib/global/qcompare.h +++ b/src/corelib/global/qcompare.h @@ -45,6 +45,7 @@ #endif #include <QtCore/qglobal.h> +#include <QtCore/qcompare_impl.h> QT_BEGIN_NAMESPACE @@ -65,16 +66,6 @@ enum class Uncomparable : CompareUnderlyingType Unordered = -127 }; -// [cmp.categories.pre] / 3, but using a safe bool trick -// and also rejecting std::nullptr_t (unlike the example) -class CompareAgainstLiteralZero { -public: - using SafeZero = void (CompareAgainstLiteralZero::*)(); - Q_IMPLICIT constexpr CompareAgainstLiteralZero(SafeZero) noexcept {} - - template <typename T, std::enable_if_t<!std::is_same_v<T, int>, bool> = false> - CompareAgainstLiteralZero(T) = delete; -}; } // namespace QtPrivate // [cmp.partialord] |