Fix compilation for recursive Qt containers
The operator checks cause compilation errors when trying to check for their existence for recursive containers. This happens because of trying to check for the operators on the template parameter type(s), that inherit from the container itself, which leads to compilation errors. Introduced alternative versions of the operator checks (with _container suffix), that first check if the container is recursive, i.e. any of its template parameter types inherits from the given container, and skips the operator check, if that's the case. The fix is done for all Qt container types that had the problem, except for QVarLengthArray and QContiguousCache, which don't compile with recursive parameter types for unrelated reasons. Fixes: QTBUG-91707 Pick-to: 6.2 6.1 Change-Id: Ia1e7240b4ce240c1c44f00ca680717d182df7550 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
4cde0e484c
commit
9f13842fe6
@ -335,17 +335,29 @@ struct has_operator_equal : detail::expand_operator_equal<T> {};
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr bool has_operator_equal_v = has_operator_equal<T>::value;
|
inline constexpr bool has_operator_equal_v = has_operator_equal<T>::value;
|
||||||
|
|
||||||
|
template <typename Container, typename T>
|
||||||
|
using has_operator_equal_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_equal<T>>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct has_operator_less_than : detail::expand_operator_less_than<T> {};
|
struct has_operator_less_than : detail::expand_operator_less_than<T> {};
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr bool has_operator_less_than_v = has_operator_less_than<T>::value;
|
inline constexpr bool has_operator_less_than_v = has_operator_less_than<T>::value;
|
||||||
|
|
||||||
|
template <typename Container, typename T>
|
||||||
|
using has_operator_less_than_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_less_than<T>>;
|
||||||
|
|
||||||
template <typename ...T>
|
template <typename ...T>
|
||||||
using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>;
|
using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>;
|
||||||
|
|
||||||
|
template <typename Container, typename ...T>
|
||||||
|
using compare_eq_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal_container<Container, T>...>, bool>;
|
||||||
|
|
||||||
template <typename ...T>
|
template <typename ...T>
|
||||||
using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>;
|
using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>;
|
||||||
|
|
||||||
|
template <typename Container, typename ...T>
|
||||||
|
using compare_lt_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>...>, bool>;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -363,6 +375,9 @@ struct has_ostream_operator<Stream, T, std::void_t<decltype(detail::reference<St
|
|||||||
template <typename Stream, typename T>
|
template <typename Stream, typename T>
|
||||||
inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value;
|
inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value;
|
||||||
|
|
||||||
|
template <typename Stream, typename Container, typename T>
|
||||||
|
using has_ostream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_ostream_operator<Stream, T>>;
|
||||||
|
|
||||||
template <typename Stream, typename, typename = void>
|
template <typename Stream, typename, typename = void>
|
||||||
struct has_istream_operator : std::false_type {};
|
struct has_istream_operator : std::false_type {};
|
||||||
template <typename Stream, typename T>
|
template <typename Stream, typename T>
|
||||||
@ -370,6 +385,8 @@ struct has_istream_operator<Stream, T, std::void_t<decltype(detail::reference<St
|
|||||||
: std::true_type {};
|
: std::true_type {};
|
||||||
template <typename Stream, typename T>
|
template <typename Stream, typename T>
|
||||||
inline constexpr bool has_istream_operator_v = has_istream_operator<Stream, T>::value;
|
inline constexpr bool has_istream_operator_v = has_istream_operator<Stream, T>::value;
|
||||||
|
template <typename Stream, typename Container, typename T>
|
||||||
|
using has_istream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_istream_operator<Stream, T>>;
|
||||||
|
|
||||||
template <typename Stream, typename T>
|
template <typename Stream, typename T>
|
||||||
inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>;
|
inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>;
|
||||||
|
@ -244,8 +244,12 @@ template<typename ...T>
|
|||||||
using QDebugIfHasDebugStream =
|
using QDebugIfHasDebugStream =
|
||||||
std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDebug, T>...>, QDebug>;
|
std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDebug, T>...>, QDebug>;
|
||||||
|
|
||||||
|
template<typename Container, typename ...T>
|
||||||
|
using QDebugIfHasDebugStreamContainer =
|
||||||
|
std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDebug, Container, T>...>, QDebug>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QList<T> &vec)
|
inline QDebugIfHasDebugStreamContainer<QList<T>, T> operator<<(QDebug debug, const QList<T> &vec)
|
||||||
{
|
{
|
||||||
return QtPrivate::printSequentialContainer(debug, "QList", vec);
|
return QtPrivate::printSequentialContainer(debug, "QList", vec);
|
||||||
}
|
}
|
||||||
@ -281,25 +285,25 @@ inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const std::multim
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const QMap<Key, T> &map)
|
inline QDebugIfHasDebugStreamContainer<QMap<Key, T>, Key, T> operator<<(QDebug debug, const QMap<Key, T> &map)
|
||||||
{
|
{
|
||||||
return QtPrivate::printAssociativeContainer(debug, "QMap", map);
|
return QtPrivate::printAssociativeContainer(debug, "QMap", map);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const QMultiMap<Key, T> &map)
|
inline QDebugIfHasDebugStreamContainer<QMultiMap<Key, T>, Key, T> operator<<(QDebug debug, const QMultiMap<Key, T> &map)
|
||||||
{
|
{
|
||||||
return QtPrivate::printAssociativeContainer(debug, "QMultiMap", map);
|
return QtPrivate::printAssociativeContainer(debug, "QMultiMap", map);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const QHash<Key, T> &hash)
|
inline QDebugIfHasDebugStreamContainer<QHash<Key, T>, Key, T> operator<<(QDebug debug, const QHash<Key, T> &hash)
|
||||||
{
|
{
|
||||||
return QtPrivate::printAssociativeContainer(debug, "QHash", hash);
|
return QtPrivate::printAssociativeContainer(debug, "QHash", hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDebugIfHasDebugStream<Key, T> operator<<(QDebug debug, const QMultiHash<Key, T> &hash)
|
inline QDebugIfHasDebugStreamContainer<QMultiHash<Key, T>, Key, T> operator<<(QDebug debug, const QMultiHash<Key, T> &hash)
|
||||||
{
|
{
|
||||||
return QtPrivate::printAssociativeContainer(debug, "QMultiHash", hash);
|
return QtPrivate::printAssociativeContainer(debug, "QMultiHash", hash);
|
||||||
}
|
}
|
||||||
@ -313,7 +317,7 @@ inline QDebugIfHasDebugStream<T1, T2> operator<<(QDebug debug, const std::pair<T
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline QDebugIfHasDebugStream<T> operator<<(QDebug debug, const QSet<T> &set)
|
inline QDebugIfHasDebugStreamContainer<QSet<T>, T> operator<<(QDebug debug, const QSet<T> &set)
|
||||||
{
|
{
|
||||||
return QtPrivate::printSequentialContainer(debug, "QSet", set);
|
return QtPrivate::printSequentialContainer(debug, "QSet", set);
|
||||||
}
|
}
|
||||||
|
@ -351,9 +351,16 @@ QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
|
|||||||
template<typename ...T>
|
template<typename ...T>
|
||||||
using QDataStreamIfHasOStreamOperators =
|
using QDataStreamIfHasOStreamOperators =
|
||||||
std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDataStream, T>...>, QDataStream &>;
|
std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDataStream, T>...>, QDataStream &>;
|
||||||
|
template<typename Container, typename ...T>
|
||||||
|
using QDataStreamIfHasOStreamOperatorsContainer =
|
||||||
|
std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDataStream, Container, T>...>, QDataStream &>;
|
||||||
|
|
||||||
template<typename ...T>
|
template<typename ...T>
|
||||||
using QDataStreamIfHasIStreamOperators =
|
using QDataStreamIfHasIStreamOperators =
|
||||||
std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator<QDataStream, T>...>, QDataStream &>;
|
std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator<QDataStream, T>...>, QDataStream &>;
|
||||||
|
template<typename Container, typename ...T>
|
||||||
|
using QDataStreamIfHasIStreamOperatorsContainer =
|
||||||
|
std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator_container<QDataStream, Container, T>...>, QDataStream &>;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
QDataStream inline functions
|
QDataStream inline functions
|
||||||
@ -425,74 +432,74 @@ operator>>(QDataStream &s, T &t)
|
|||||||
{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
|
{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline QDataStreamIfHasIStreamOperators<T> operator>>(QDataStream &s, QList<T> &v)
|
inline QDataStreamIfHasIStreamOperatorsContainer<QList<T>, T> operator>>(QDataStream &s, QList<T> &v)
|
||||||
{
|
{
|
||||||
return QtPrivate::readArrayBasedContainer(s, v);
|
return QtPrivate::readArrayBasedContainer(s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline QDataStreamIfHasOStreamOperators<T> operator<<(QDataStream &s, const QList<T> &v)
|
inline QDataStreamIfHasOStreamOperatorsContainer<QList<T>, T> operator<<(QDataStream &s, const QList<T> &v)
|
||||||
{
|
{
|
||||||
return QtPrivate::writeSequentialContainer(s, v);
|
return QtPrivate::writeSequentialContainer(s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline QDataStreamIfHasIStreamOperators<T> operator>>(QDataStream &s, QSet<T> &set)
|
inline QDataStreamIfHasIStreamOperatorsContainer<QSet<T>, T> operator>>(QDataStream &s, QSet<T> &set)
|
||||||
{
|
{
|
||||||
return QtPrivate::readListBasedContainer(s, set);
|
return QtPrivate::readListBasedContainer(s, set);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline QDataStreamIfHasOStreamOperators<T> operator<<(QDataStream &s, const QSet<T> &set)
|
inline QDataStreamIfHasOStreamOperatorsContainer<QSet<T>, T> operator<<(QDataStream &s, const QSet<T> &set)
|
||||||
{
|
{
|
||||||
return QtPrivate::writeSequentialContainer(s, set);
|
return QtPrivate::writeSequentialContainer(s, set);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDataStreamIfHasIStreamOperators<Key, T> operator>>(QDataStream &s, QHash<Key, T> &hash)
|
inline QDataStreamIfHasIStreamOperatorsContainer<QHash<Key, T>, Key, T> operator>>(QDataStream &s, QHash<Key, T> &hash)
|
||||||
{
|
{
|
||||||
return QtPrivate::readAssociativeContainer(s, hash);
|
return QtPrivate::readAssociativeContainer(s, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
|
|
||||||
inline QDataStreamIfHasOStreamOperators<Key, T> operator<<(QDataStream &s, const QHash<Key, T> &hash)
|
inline QDataStreamIfHasOStreamOperatorsContainer<QHash<Key, T>, Key, T> operator<<(QDataStream &s, const QHash<Key, T> &hash)
|
||||||
{
|
{
|
||||||
return QtPrivate::writeAssociativeContainer(s, hash);
|
return QtPrivate::writeAssociativeContainer(s, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDataStreamIfHasIStreamOperators<Key, T> operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
|
inline QDataStreamIfHasIStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
|
||||||
{
|
{
|
||||||
return QtPrivate::readAssociativeContainer(s, hash);
|
return QtPrivate::readAssociativeContainer(s, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDataStreamIfHasOStreamOperators<Key, T> operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
|
inline QDataStreamIfHasOStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
|
||||||
{
|
{
|
||||||
return QtPrivate::writeAssociativeMultiContainer(s, hash);
|
return QtPrivate::writeAssociativeMultiContainer(s, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDataStreamIfHasIStreamOperators<Key, T> operator>>(QDataStream &s, QMap<Key, T> &map)
|
inline QDataStreamIfHasIStreamOperatorsContainer<QMap<Key, T>, Key, T> operator>>(QDataStream &s, QMap<Key, T> &map)
|
||||||
{
|
{
|
||||||
return QtPrivate::readAssociativeContainer(s, map);
|
return QtPrivate::readAssociativeContainer(s, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDataStreamIfHasOStreamOperators<Key, T> operator<<(QDataStream &s, const QMap<Key, T> &map)
|
inline QDataStreamIfHasOStreamOperatorsContainer<QMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMap<Key, T> &map)
|
||||||
{
|
{
|
||||||
return QtPrivate::writeAssociativeContainer(s, map);
|
return QtPrivate::writeAssociativeContainer(s, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDataStreamIfHasIStreamOperators<Key, T> operator>>(QDataStream &s, QMultiMap<Key, T> &map)
|
inline QDataStreamIfHasIStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator>>(QDataStream &s, QMultiMap<Key, T> &map)
|
||||||
{
|
{
|
||||||
return QtPrivate::readAssociativeContainer(s, map);
|
return QtPrivate::readAssociativeContainer(s, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Key, class T>
|
template <class Key, class T>
|
||||||
inline QDataStreamIfHasOStreamOperators<Key, T> operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
|
inline QDataStreamIfHasOStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
|
||||||
{
|
{
|
||||||
return QtPrivate::writeAssociativeMultiContainer(s, map);
|
return QtPrivate::writeAssociativeMultiContainer(s, map);
|
||||||
}
|
}
|
||||||
|
@ -820,7 +820,7 @@ public:
|
|||||||
void swap(QHash &other) noexcept { qSwap(d, other.d); }
|
void swap(QHash &other) noexcept { qSwap(d, other.d); }
|
||||||
|
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
QTypeTraits::compare_eq_result<U> operator==(const QHash &other) const noexcept
|
QTypeTraits::compare_eq_result_container<QHash, U> operator==(const QHash &other) const noexcept
|
||||||
{
|
{
|
||||||
if (d == other.d)
|
if (d == other.d)
|
||||||
return true;
|
return true;
|
||||||
@ -836,7 +836,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
QTypeTraits::compare_eq_result<U> operator!=(const QHash &other) const noexcept
|
QTypeTraits::compare_eq_result_container<QHash, U> operator!=(const QHash &other) const noexcept
|
||||||
{ return !(*this == other); }
|
{ return !(*this == other); }
|
||||||
|
|
||||||
inline qsizetype size() const noexcept { return d ? qsizetype(d->size) : 0; }
|
inline qsizetype size() const noexcept { return d ? qsizetype(d->size) : 0; }
|
||||||
|
@ -290,7 +290,7 @@ public:
|
|||||||
void swap(QList<T> &other) noexcept { qSwap(d, other.d); }
|
void swap(QList<T> &other) noexcept { qSwap(d, other.d); }
|
||||||
|
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
QTypeTraits::compare_eq_result<U> operator==(const QList &other) const
|
QTypeTraits::compare_eq_result_container<QList, U> operator==(const QList &other) const
|
||||||
{
|
{
|
||||||
if (size() != other.size())
|
if (size() != other.size())
|
||||||
return false;
|
return false;
|
||||||
@ -301,13 +301,13 @@ public:
|
|||||||
return d->compare(begin(), other.begin(), size());
|
return d->compare(begin(), other.begin(), size());
|
||||||
}
|
}
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
QTypeTraits::compare_eq_result<U> operator!=(const QList &other) const
|
QTypeTraits::compare_eq_result_container<QList, U> operator!=(const QList &other) const
|
||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
QTypeTraits::compare_lt_result<U> operator<(const QList &other) const
|
QTypeTraits::compare_lt_result_container<QList, U> operator<(const QList &other) const
|
||||||
noexcept(noexcept(std::lexicographical_compare<typename QList<U>::const_iterator,
|
noexcept(noexcept(std::lexicographical_compare<typename QList<U>::const_iterator,
|
||||||
typename QList::const_iterator>(
|
typename QList::const_iterator>(
|
||||||
std::declval<QList<U>>().begin(), std::declval<QList<U>>().end(),
|
std::declval<QList<U>>().begin(), std::declval<QList<U>>().end(),
|
||||||
@ -318,21 +318,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
QTypeTraits::compare_lt_result<U> operator>(const QList &other) const
|
QTypeTraits::compare_lt_result_container<QList, U> operator>(const QList &other) const
|
||||||
noexcept(noexcept(other < std::declval<QList<U>>()))
|
noexcept(noexcept(other < std::declval<QList<U>>()))
|
||||||
{
|
{
|
||||||
return other < *this;
|
return other < *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
QTypeTraits::compare_lt_result<U> operator<=(const QList &other) const
|
QTypeTraits::compare_lt_result_container<QList, U> operator<=(const QList &other) const
|
||||||
noexcept(noexcept(other < std::declval<QList<U>>()))
|
noexcept(noexcept(other < std::declval<QList<U>>()))
|
||||||
{
|
{
|
||||||
return !(other < *this);
|
return !(other < *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
QTypeTraits::compare_lt_result<U> operator>=(const QList &other) const
|
QTypeTraits::compare_lt_result_container<QList, U> operator>=(const QList &other) const
|
||||||
noexcept(noexcept(std::declval<QList<U>>() < other))
|
noexcept(noexcept(std::declval<QList<U>>() < other))
|
||||||
{
|
{
|
||||||
return !(*this < other);
|
return !(*this < other);
|
||||||
|
@ -277,7 +277,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename AKey = Key, typename AT = T> friend
|
template <typename AKey = Key, typename AT = T> friend
|
||||||
QTypeTraits::compare_eq_result<AKey, AT> operator==(const QMap &lhs, const QMap &rhs)
|
QTypeTraits::compare_eq_result_container<QMap, AKey, AT> operator==(const QMap &lhs, const QMap &rhs)
|
||||||
{
|
{
|
||||||
if (lhs.d == rhs.d)
|
if (lhs.d == rhs.d)
|
||||||
return true;
|
return true;
|
||||||
@ -288,7 +288,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename AKey = Key, typename AT = T> friend
|
template <typename AKey = Key, typename AT = T> friend
|
||||||
QTypeTraits::compare_eq_result<AKey, AT> operator!=(const QMap &lhs, const QMap &rhs)
|
QTypeTraits::compare_eq_result_container<QMap, AKey, AT> operator!=(const QMap &lhs, const QMap &rhs)
|
||||||
{
|
{
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
@ -905,7 +905,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename AKey = Key, typename AT = T> friend
|
template <typename AKey = Key, typename AT = T> friend
|
||||||
QTypeTraits::compare_eq_result<AKey, AT> operator==(const QMultiMap &lhs, const QMultiMap &rhs)
|
QTypeTraits::compare_eq_result_container<QMultiMap, AKey, AT> operator==(const QMultiMap &lhs, const QMultiMap &rhs)
|
||||||
{
|
{
|
||||||
if (lhs.d == rhs.d)
|
if (lhs.d == rhs.d)
|
||||||
return true;
|
return true;
|
||||||
@ -916,7 +916,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename AKey = Key, typename AT = T> friend
|
template <typename AKey = Key, typename AT = T> friend
|
||||||
QTypeTraits::compare_eq_result<AKey, AT> operator!=(const QMultiMap &lhs, const QMultiMap &rhs)
|
QTypeTraits::compare_eq_result_container<QMultiMap, AKey, AT> operator!=(const QMultiMap &lhs, const QMultiMap &rhs)
|
||||||
{
|
{
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
@ -72,10 +72,10 @@ public:
|
|||||||
inline void swap(QSet<T> &other) noexcept { q_hash.swap(other.q_hash); }
|
inline void swap(QSet<T> &other) noexcept { q_hash.swap(other.q_hash); }
|
||||||
|
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
QTypeTraits::compare_eq_result<U> operator==(const QSet<T> &other) const
|
QTypeTraits::compare_eq_result_container<QSet, U> operator==(const QSet<T> &other) const
|
||||||
{ return q_hash == other.q_hash; }
|
{ return q_hash == other.q_hash; }
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
QTypeTraits::compare_eq_result<U> operator!=(const QSet<T> &other) const
|
QTypeTraits::compare_eq_result_container<QSet, U> operator!=(const QSet<T> &other) const
|
||||||
{ return q_hash != other.q_hash; }
|
{ return q_hash != other.q_hash; }
|
||||||
|
|
||||||
inline qsizetype size() const { return q_hash.size(); }
|
inline qsizetype size() const { return q_hash.size(); }
|
||||||
|
@ -160,6 +160,150 @@ struct Pod {
|
|||||||
int i1, i2;
|
int i1, i2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Compile-time checks for recursive containers
|
||||||
|
struct Dummy
|
||||||
|
{
|
||||||
|
bool operator==(const Dummy &) const { return false; }
|
||||||
|
bool operator<(const Dummy &) const { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RecursiveList : public QList<RecursiveList> {};
|
||||||
|
struct RecursiveSet : public QSet<RecursiveSet> {};
|
||||||
|
struct RecursiveMapV : public QMap<Dummy, RecursiveMapV> {};
|
||||||
|
struct RecursiveMapK : public QMap<RecursiveMapK, Dummy> {};
|
||||||
|
struct RecursiveMultiMapV : public QMultiMap<Dummy, RecursiveMultiMapV> {};
|
||||||
|
struct RecursiveMultiMapK : public QMultiMap<RecursiveMultiMapK, Dummy> {};
|
||||||
|
struct RecursiveHashV : public QHash<Dummy, RecursiveHashV> {};
|
||||||
|
struct RecursiveHashK : public QHash<RecursiveHashK, Dummy> {};
|
||||||
|
struct RecursiveMultiHashV : public QMultiHash<Dummy, RecursiveMultiHashV> {};
|
||||||
|
struct RecursiveMultiHashK : public QMultiHash<RecursiveMultiHashK, Dummy> {};
|
||||||
|
|
||||||
|
struct Empty {};
|
||||||
|
struct NoCmpParamRecursiveMapV : public QMap<Empty, NoCmpParamRecursiveMapV> {};
|
||||||
|
struct NoCmpParamRecursiveMapK : public QMap<NoCmpParamRecursiveMapK, Empty> {};
|
||||||
|
struct NoCmpParamRecursiveMultiMapV : public QMultiMap<Empty, NoCmpParamRecursiveMultiMapV> {};
|
||||||
|
struct NoCmpParamRecursiveMultiMapK : public QMultiMap<NoCmpParamRecursiveMultiMapK, Empty> {};
|
||||||
|
struct NoCmpParamRecursiveHashV : public QHash<Empty, NoCmpParamRecursiveHashV> {};
|
||||||
|
struct NoCmpParamRecursiveHashK : public QHash<NoCmpParamRecursiveHashK, Empty> {};
|
||||||
|
struct NoCmpParamRecursiveMultiHashV : public QMultiHash<Empty, NoCmpParamRecursiveMultiHashV> {};
|
||||||
|
struct NoCmpParamRecursiveMultiHashK : public QMultiHash<NoCmpParamRecursiveMultiHashK, Empty> {};
|
||||||
|
|
||||||
|
struct NoCmpRecursiveList : public QList<NoCmpRecursiveList>
|
||||||
|
{
|
||||||
|
bool operator==(const RecursiveList &) const = delete;
|
||||||
|
bool operator<(const RecursiveList &) const = delete;
|
||||||
|
};
|
||||||
|
struct NoCmpRecursiveSet : public QSet<NoCmpRecursiveSet>
|
||||||
|
{
|
||||||
|
bool operator==(const NoCmpRecursiveSet &) const = delete;
|
||||||
|
};
|
||||||
|
struct NoCmpRecursiveMapV : public QMap<Dummy, NoCmpRecursiveMapV>
|
||||||
|
{
|
||||||
|
bool operator==(const NoCmpRecursiveMapV &) const = delete;
|
||||||
|
};
|
||||||
|
struct NoCmpRecursiveMapK : public QMap<NoCmpRecursiveMapK, Dummy>
|
||||||
|
{
|
||||||
|
bool operator==(const NoCmpRecursiveMapK &) const = delete;
|
||||||
|
};
|
||||||
|
struct NoCmpRecursiveMultiMapV : public QMultiMap<Dummy, NoCmpRecursiveMultiMapV>
|
||||||
|
{
|
||||||
|
bool operator==(const NoCmpRecursiveMultiMapV &) const = delete;
|
||||||
|
};
|
||||||
|
struct NoCmpRecursiveMultiMapK : public QMultiMap<NoCmpRecursiveMultiMapK, Dummy>
|
||||||
|
{
|
||||||
|
bool operator==(const NoCmpRecursiveMultiMapK &) const = delete;
|
||||||
|
};
|
||||||
|
struct NoCmpRecursiveHashV : public QHash<Dummy, NoCmpRecursiveHashV>
|
||||||
|
{
|
||||||
|
bool operator==(const NoCmpRecursiveHashV &) const = delete;
|
||||||
|
};
|
||||||
|
struct NoCmpRecursiveHashK : public QHash<NoCmpRecursiveHashK, Dummy>
|
||||||
|
{
|
||||||
|
bool operator==(const NoCmpRecursiveHashK &) const = delete;
|
||||||
|
};
|
||||||
|
struct NoCmpRecursiveMultiHashV : public QMultiHash<Dummy, NoCmpRecursiveMultiHashV>
|
||||||
|
{
|
||||||
|
bool operator==(const NoCmpRecursiveMultiHashV &) const = delete;
|
||||||
|
};
|
||||||
|
struct NoCmpRecursiveMultiHashK : public QMultiHash<NoCmpRecursiveMultiHashK, Dummy>
|
||||||
|
{
|
||||||
|
bool operator==(const NoCmpRecursiveMultiHashK &) const = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint qHash(const Dummy &) { return 0; }
|
||||||
|
uint qHash(const RecursiveSet &) { return 0; }
|
||||||
|
uint qHash(const RecursiveHashK &) { return 0; }
|
||||||
|
uint qHash(const RecursiveHashV &) { return 0; }
|
||||||
|
uint qHash(const RecursiveMultiHashK &) { return 0; }
|
||||||
|
uint qHash(const RecursiveMultiHashV &) { return 0; }
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(RecursiveList);
|
||||||
|
Q_DECLARE_METATYPE(RecursiveSet);
|
||||||
|
Q_DECLARE_METATYPE(RecursiveMapV);
|
||||||
|
Q_DECLARE_METATYPE(RecursiveMapK);
|
||||||
|
Q_DECLARE_METATYPE(RecursiveMultiMapV);
|
||||||
|
Q_DECLARE_METATYPE(RecursiveMultiMapK);
|
||||||
|
Q_DECLARE_METATYPE(RecursiveHashV);
|
||||||
|
Q_DECLARE_METATYPE(RecursiveHashK);
|
||||||
|
Q_DECLARE_METATYPE(RecursiveMultiHashV);
|
||||||
|
Q_DECLARE_METATYPE(RecursiveMultiHashK);
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(NoCmpParamRecursiveMapV);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpParamRecursiveMapK);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpParamRecursiveMultiMapV);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpParamRecursiveMultiMapK);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpParamRecursiveHashK);
|
||||||
|
// TODO: fix, this requires operator== from key type (QTBUG-96256)
|
||||||
|
// Q_DECLARE_METATYPE(NoCmpParamRecursiveHashV);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpParamRecursiveMultiHashK);
|
||||||
|
// TODO: fix, this requires operator== from key type (QTBUG-96256)
|
||||||
|
// Q_DECLARE_METATYPE(NoCmpParamRecursiveMultiHashK);
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(NoCmpRecursiveList);
|
||||||
|
// TODO: fix, this requires operator== (QTBUG-96257)
|
||||||
|
// Q_DECLARE_METATYPE(NoCmpRecursiveSet);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpRecursiveMapV);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpRecursiveMapK);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpRecursiveMultiMapV);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpRecursiveMultiMapK);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpRecursiveHashV);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpRecursiveHashK);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpRecursiveMultiHashV);
|
||||||
|
Q_DECLARE_METATYPE(NoCmpRecursiveMultiHashK);
|
||||||
|
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<RecursiveList>);
|
||||||
|
static_assert(QTypeTraits::has_operator_less_than_v<RecursiveList>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<RecursiveSet>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<RecursiveMapV>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<RecursiveMapK>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<RecursiveMultiMapV>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<RecursiveMultiMapK>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<RecursiveHashV>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<RecursiveHashK>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<RecursiveMultiHashV>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<RecursiveMultiHashK>);
|
||||||
|
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMapV>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMapK>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMultiMapV>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMultiMapK>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveHashV>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveHashK>);
|
||||||
|
static_assert(QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMultiHashV>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpParamRecursiveMultiHashK>);
|
||||||
|
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveList>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_less_than_v<NoCmpRecursiveList>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveSet>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMapV>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMapK>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMultiMapV>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMultiMapK>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveHashV>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveHashK>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMultiHashV>);
|
||||||
|
static_assert(!QTypeTraits::has_operator_equal_v<NoCmpRecursiveMultiHashK>);
|
||||||
|
|
||||||
void tst_Collections::typeinfo()
|
void tst_Collections::typeinfo()
|
||||||
{
|
{
|
||||||
QVERIFY(QTypeInfo<int*>::isPointer);
|
QVERIFY(QTypeInfo<int*>::isPointer);
|
||||||
|
Loading…
Reference in New Issue
Block a user