summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-06-05 21:01:29 +0200
committerLars Knoll <lars.knoll@qt.io>2020-07-08 14:13:56 +0200
commit0e2cfdedf261a9d29d7466bd26545549479d9f8a (patch)
tree8c6b3eaaad7463bf2e019b0694286aa065544138 /src
parent16bc995fd1eba4f7485226f319e7736ca19040bc (diff)
Constrain the comparison operators for our container classes
This had already been in very few places, where we ran into issues with this before. More generic constraints here will significantly reduce the amount of error messages a user has to parse in case he tries to instantiate an operator by accident (or with a lacking comparison operator for one of it's template arguments). Change-Id: I1521d19c55d99732d9742402bd534c390a8e4242 Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qtypeinfo.h5
-rw-r--r--src/corelib/tools/qcontiguouscache.h37
-rw-r--r--src/corelib/tools/qhash.h7
-rw-r--r--src/corelib/tools/qlist.h6
-rw-r--r--src/corelib/tools/qmap.h44
-rw-r--r--src/corelib/tools/qset.h10
-rw-r--r--src/corelib/tools/qvarlengtharray.h12
7 files changed, 67 insertions, 54 deletions
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 8b31fb4a81..9b85a41266 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -432,6 +432,11 @@ struct has_operator_less_than : detail::expand_operator_less_than<T> {};
template<typename T>
constexpr bool has_operator_less_than_v = has_operator_less_than<T>::value;
+template <typename ...T>
+using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>;
+
+template <typename ...T>
+using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>;
}
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
index 81361f219a..79f5e3fdb6 100644
--- a/src/corelib/tools/qcontiguouscache.h
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -97,8 +97,25 @@ public:
inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other) noexcept
{ qSwap(d, other.d); return *this; }
inline void swap(QContiguousCache<T> &other) noexcept { qSwap(d, other.d); }
- bool operator==(const QContiguousCache<T> &other) const;
- inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); }
+
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator==(const QContiguousCache<T> &other) const
+ {
+ if (other.d == d)
+ return true;
+ if (other.d->start != d->start
+ || other.d->count != d->count
+ || other.d->offset != d->offset
+ || other.d->alloc != d->alloc)
+ return false;
+ for (qsizetype i = firstIndex(); i <= lastIndex(); ++i)
+ if (!(at(i) == other.at(i)))
+ return false;
+ return true;
+ }
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator!=(const QContiguousCache<T> &other) const
+ { return !(*this == other); }
inline qsizetype capacity() const {return d->alloc; }
inline qsizetype count() const { return d->count; }
@@ -272,22 +289,6 @@ QContiguousCache<T> &QContiguousCache<T>::operator=(const QContiguousCache<T> &o
}
template <typename T>
-bool QContiguousCache<T>::operator==(const QContiguousCache<T> &other) const
-{
- if (other.d == d)
- return true;
- if (other.d->start != d->start
- || other.d->count != d->count
- || other.d->offset != d->offset
- || other.d->alloc != d->alloc)
- return false;
- for (qsizetype i = firstIndex(); i <= lastIndex(); ++i)
- if (!(at(i) == other.at(i)))
- return false;
- return true;
-}
-
-template <typename T>
void QContiguousCache<T>::freeData(Data *x)
{
if (QTypeInfo<T>::isComplex) {
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 2de3989eb2..8825372c03 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -782,7 +782,8 @@ public:
#endif
void swap(QHash &other) noexcept { qSwap(d, other.d); }
- bool operator==(const QHash &other) const noexcept
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator==(const QHash &other) const noexcept
{
if (d == other.d)
return true;
@@ -797,7 +798,9 @@ public:
// all values must be the same as size is the same
return true;
}
- bool operator!=(const QHash &other) const noexcept { return !(*this == other); }
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator!=(const QHash &other) const noexcept
+ { return !(*this == other); }
inline qsizetype size() const noexcept { return d ? qsizetype(d->size) : 0; }
inline bool isEmpty() const noexcept { return !d || d->size == 0; }
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 3b9eb154ed..c2e5e12a1d 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -162,7 +162,8 @@ public:
void swap(QList<T> &other) noexcept { qSwap(d, other.d); }
- friend bool operator==(const QList &l, const QList &r)
+ template <typename U = T>
+ friend QTypeTraits::compare_eq_result<U> operator==(const QList &l, const QList &r)
{
if (l.size() != r.size())
return false;
@@ -172,7 +173,8 @@ public:
// do element-by-element comparison
return l.d->compare(l.begin(), r.begin(), l.size());
}
- friend bool operator!=(const QList &l, const QList &r)
+ template <typename U = T>
+ friend QTypeTraits::compare_eq_result<U> operator!=(const QList &l, const QList &r)
{
return !(l == r);
}
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index a44f0088d3..d3e27f09ef 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -347,8 +347,28 @@ public:
explicit QMap(const typename std::map<Key, T> &other);
std::map<Key, T> toStdMap() const;
- bool operator==(const QMap<Key, T> &other) const;
- inline bool operator!=(const QMap<Key, T> &other) const { return !(*this == other); }
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator==(const QMap<Key, T> &other) const
+ {
+ if (size() != other.size())
+ return false;
+ if (d == other.d)
+ return true;
+
+ const_iterator it1 = begin();
+ const_iterator it2 = other.begin();
+
+ while (it1 != end()) {
+ if (!(it1.value() == it2.value()) || qMapLessThanKey(it1.key(), it2.key()) || qMapLessThanKey(it2.key(), it1.key()))
+ return false;
+ ++it2;
+ ++it1;
+ }
+ return true;
+ }
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator!=(const QMap<Key, T> &other) const
+ { return !(*this == other); }
inline qsizetype size() const { return d->size; }
@@ -1045,26 +1065,6 @@ Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::upperBound(const
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE bool QMap<Key, T>::operator==(const QMap<Key, T> &other) const
-{
- if (size() != other.size())
- return false;
- if (d == other.d)
- return true;
-
- const_iterator it1 = begin();
- const_iterator it2 = other.begin();
-
- while (it1 != end()) {
- if (!(it1.value() == it2.value()) || qMapLessThanKey(it1.key(), it2.key()) || qMapLessThanKey(it2.key(), it1.key()))
- return false;
- ++it2;
- ++it1;
- }
- return true;
-}
-
-template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QMap<Key, T>::QMap(const std::map<Key, T> &other)
{
d = QMapData<Key, T>::create();
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index f078e62999..bb817ccb3c 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -71,10 +71,12 @@ public:
inline void swap(QSet<T> &other) noexcept { q_hash.swap(other.q_hash); }
- inline bool operator==(const QSet<T> &other) const
- { return q_hash == other.q_hash; }
- inline bool operator!=(const QSet<T> &other) const
- { return q_hash != other.q_hash; }
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator==(const QSet<T> &other) const
+ { return q_hash == other.q_hash; }
+ template <typename U = T>
+ QTypeTraits::compare_eq_result<U> operator!=(const QSet<T> &other) const
+ { return q_hash != other.q_hash; }
inline int size() const { return q_hash.size(); }
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index cea0e14d41..fccdfad081 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -605,7 +605,7 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
}
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+QTypeTraits::compare_eq_result<T> operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
{
if (l.size() != r.size())
return false;
@@ -616,13 +616,13 @@ bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T,
}
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
+QTypeTraits::compare_eq_result<T> operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
{
return !(l == r);
}
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-bool operator<(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+QTypeTraits::compare_lt_result<T> operator<(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end())))
{
@@ -631,21 +631,21 @@ bool operator<(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T
}
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-inline bool operator>(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+QTypeTraits::compare_lt_result<T> operator>(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
noexcept(noexcept(lhs < rhs))
{
return rhs < lhs;
}
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-inline bool operator<=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+QTypeTraits::compare_lt_result<T> operator<=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
noexcept(noexcept(lhs < rhs))
{
return !(lhs > rhs);
}
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
-inline bool operator>=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
+QTypeTraits::compare_lt_result<T> operator>=(const QVarLengthArray<T, Prealloc1> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
noexcept(noexcept(lhs < rhs))
{
return !(lhs < rhs);