QMap: use std::less for defining an order between pointers

Reinterpret_cast()ing a pointer to a suitably sized integer is not guaranteed
to always give the same result for the same pointer (!). Therefore the
resulting integers are not comparable in a meaningful way. std::less is
supposed to be used to compare arbitrary pointers, so use it.

(Hopefully and reasonably, under the hood std::less does exactly what we
were doing, so this isn't BiC.)

Change-Id: I9960b3d6e35657fe7a25b842054f5d338280e850
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Giuseppe D'Angelo 2016-11-01 08:40:20 +00:00
parent 888b3f5045
commit 1da70af724
2 changed files with 7 additions and 8 deletions

View File

@ -399,7 +399,9 @@ void QMapDataBase::freeData(QMapDataBase *d)
With QMap, the items are always sorted by key. With QMap, the items are always sorted by key.
\li The key type of a QHash must provide operator==() and a global \li The key type of a QHash must provide operator==() and a global
qHash(Key) function. The key type of a QMap must provide qHash(Key) function. The key type of a QMap must provide
operator<() specifying a total order. operator<() specifying a total order. Since Qt 5.8.1 it is also safe
to use a pointer type as key, even if the underlying operator<()
does not provide a total order.
\endlist \endlist
Here's an example QMap with QString keys and \c int values: Here's an example QMap with QString keys and \c int values:

View File

@ -51,6 +51,7 @@
#include <map> #include <map>
#include <new> #include <new>
#include <functional>
#ifdef Q_COMPILER_INITIALIZER_LISTS #ifdef Q_COMPILER_INITIALIZER_LISTS
#include <initializer_list> #include <initializer_list>
@ -61,11 +62,8 @@ QT_BEGIN_NAMESPACE
/* /*
QMap uses qMapLessThanKey() to compare keys. The default QMap uses qMapLessThanKey() to compare keys. The default
implementation uses operator<(). For pointer types, implementation uses operator<(). For pointer types,
qMapLessThanKey() casts the pointers to integers before it qMapLessThanKey() uses std::less (because operator<() on
compares them, because operator<() is undefined on pointers pointers can be used only between pointers in the same array).
that come from different memory blocks. (In practice, this
is only a problem when running a program such as
BoundsChecker.)
*/ */
template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key2) template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key2)
@ -75,8 +73,7 @@ template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key
template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key2) template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key2)
{ {
Q_STATIC_ASSERT(sizeof(quintptr) == sizeof(const Ptr *)); return std::less<const Ptr *>()(key1, key2);
return quintptr(key1) < quintptr(key2);
} }
struct QMapDataBase; struct QMapDataBase;