QFlags: use unsigned int when the enum's underlying is unsigned

Replace storage and operator int() return types with unsigned int
if the enum is unsigned.

This fixes a number of exisiting warnings, in particular with
Qt::MouseButton under GCC.

Change-Id: Ia12d36212329aec3e9d62a5fbd38809a6c2b36d0
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2012-09-20 15:06:11 +02:00 committed by The Qt Project
parent 26f238a80d
commit ac9be327f8
4 changed files with 46 additions and 6 deletions

5
dist/changes-5.0.0 vendored
View File

@ -62,6 +62,11 @@ information about a particular change.
- qIsDetached<> has been removed without replacement. - qIsDetached<> has been removed without replacement.
- The return type of QFlags<Enum>::operator int() now matches the Enum's underlying
type in signedness instead of always being 'int'. This was done in order to allow
QFlags over enums whose underlying type is unsigned (Qt::MouseButton is one such
enum).
- QMetaType: - QMetaType:
* QMetaType::construct() has been renamed to QMetaType::create(). * QMetaType::construct() has been renamed to QMetaType::create().
* QMetaType::unregisterType() has been removed. * QMetaType::unregisterType() has been removed.

View File

@ -44,6 +44,7 @@
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include <QtCore/qtypeinfo.h> #include <QtCore/qtypeinfo.h>
#include <QtCore/qtypetraits.h>
QT_BEGIN_HEADER QT_BEGIN_HEADER
@ -82,11 +83,18 @@ class QFlags
"long long would overflow. Qt 5.1 will have support for 64bit enums."); "long long would overflow. Qt 5.1 will have support for 64bit enums.");
struct Private; struct Private;
typedef int (Private::*Zero); typedef int (Private::*Zero);
int i;
public: public:
#ifndef qdoc
typedef typename QtPrivate::if_<
QtPrivate::is_unsigned<Enum>::value,
unsigned int,
signed int
>::type Int;
#endif
typedef Enum enum_type; typedef Enum enum_type;
// compiler-generated copy/move ctor/assignment operators are fine! // compiler-generated copy/move ctor/assignment operators are fine!
#ifdef qdoc #ifdef qdoc
typedef int Int; // the real typedef above is too complex for qdoc
inline QFlags(const QFlags &other); inline QFlags(const QFlags &other);
inline QFlags &operator=(const QFlags &other); inline QFlags &operator=(const QFlags &other);
#endif #endif
@ -101,7 +109,7 @@ public:
inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; } inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; }
inline QFlags &operator^=(Enum f) { i ^= f; return *this; } inline QFlags &operator^=(Enum f) { i ^= f; return *this; }
Q_DECL_CONSTEXPR inline operator int() const { return i; } Q_DECL_CONSTEXPR inline operator Int() const { return i; }
Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); } Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); }
Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | f)); } Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | f)); }
@ -114,7 +122,9 @@ public:
Q_DECL_CONSTEXPR inline bool operator!() const { return !i; } Q_DECL_CONSTEXPR inline bool operator!() const { return !i; }
Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == int(f) ); } Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == Int(f) ); }
private:
Int i;
}; };
#define Q_DECLARE_FLAGS(Flags, Enum)\ #define Q_DECLARE_FLAGS(Flags, Enum)\

View File

@ -171,6 +171,15 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n);
\sa QFlag \sa QFlag
*/ */
/*!
\typedef QFlags::Int
\since 5.0
Typedef for the integer type used for storage as well as for
implicit conversion. Either \c int or \c{unsigned int}, depending
on whether the enum's underlying type is signed or unsigned.
*/
/*! /*!
\typedef QFlags::enum_type \typedef QFlags::enum_type
@ -261,9 +270,11 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n);
*/ */
/*! /*!
\fn QFlags::operator int() const \fn QFlags::operator Int() const
Returns the value stored in the QFlags object as an integer. Returns the value stored in the QFlags object as an integer.
\sa Int
*/ */
/*! /*!

View File

@ -48,6 +48,7 @@ private slots:
void testFlagZeroFlag() const; void testFlagZeroFlag() const;
void testFlagMultiBits() const; void testFlagMultiBits() const;
void constExpr(); void constExpr();
void signedness();
}; };
void tst_QFlags::testFlag() const void tst_QFlags::testFlag() const
@ -123,10 +124,23 @@ void tst_QFlags::constExpr()
#endif #endif
} }
void tst_QFlags::signedness()
{
// these are all 'true' on GCC, but since the std says the
// underlying type is implementation-defined, we need to allow for
// a different signedness, so we only check that the relative
// signedness of the types matches:
Q_STATIC_ASSERT((QtPrivate::is_unsigned<Qt::MouseButton>::value ==
QtPrivate::is_unsigned<Qt::MouseButtons::Int>::value));
Q_STATIC_ASSERT((QtPrivate::is_signed<Qt::AlignmentFlag>::value ==
QtPrivate::is_signed<Qt::Alignment::Int>::value));
}
// (statically) check QTypeInfo for QFlags instantiations: // (statically) check QTypeInfo for QFlags instantiations:
enum MyEnum { Zero, One, Two, Four=4 }; enum MyEnum { Zero, One, Two, Four=4 };
Q_DECLARE_FLAGS( MyFlags, MyEnum ); Q_DECLARE_FLAGS( MyFlags, MyEnum )
Q_DECLARE_OPERATORS_FOR_FLAGS( MyFlags ); Q_DECLARE_OPERATORS_FOR_FLAGS( MyFlags )
Q_STATIC_ASSERT( !QTypeInfo<MyFlags>::isComplex ); Q_STATIC_ASSERT( !QTypeInfo<MyFlags>::isComplex );
Q_STATIC_ASSERT( !QTypeInfo<MyFlags>::isStatic ); Q_STATIC_ASSERT( !QTypeInfo<MyFlags>::isStatic );