QHash: Unconceptify heterogeneous search code
That allows the code to run in C++17 mode - at the expense of significantly worse compile time error messages, potentially worse compilation speed and harder to read code. Adjust the test type to actually model detail::is_equality_comparable_with (which requires all four relational operators even in C++17). As a drive-by, fix the return value of remove() from auto to bool. Done-with: Marc Mutz <marc.mutz@qt.io> Fixes: QTBUG-128470 Change-Id: I68df26db579c60812a18e09b76dd5712e73ccaa2 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit 7fe3cee36352c74cbaaff52e863bd0da1170affa) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
16ed1fe089
commit
722c7edf03
@ -1377,69 +1377,83 @@ private:
|
|||||||
return iterator(result.it);
|
return iterator(result.it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename K>
|
||||||
|
using if_heterogeneously_seachable = QHashPrivate::if_heterogeneously_seachable_with<Key, K>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef __cpp_concepts
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
bool remove(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
bool remove(const K &key)
|
||||||
{
|
{
|
||||||
return removeImpl(key);
|
return removeImpl(key);
|
||||||
}
|
}
|
||||||
T take(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
T take(const K &key)
|
||||||
{
|
{
|
||||||
return takeImpl(key);
|
return takeImpl(key);
|
||||||
}
|
}
|
||||||
bool contains(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
bool contains(const K &key) const
|
||||||
{
|
{
|
||||||
return d ? d->findNode(key) != nullptr : false;
|
return d ? d->findNode(key) != nullptr : false;
|
||||||
}
|
}
|
||||||
qsizetype count(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
qsizetype count(const K &key) const
|
||||||
{
|
{
|
||||||
return contains(key) ? 1 : 0;
|
return contains(key) ? 1 : 0;
|
||||||
}
|
}
|
||||||
T value(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
T value(const K &key) const noexcept
|
||||||
{
|
{
|
||||||
if (auto *v = valueImpl(key))
|
if (auto *v = valueImpl(key))
|
||||||
return *v;
|
return *v;
|
||||||
else
|
else
|
||||||
return T();
|
return T();
|
||||||
}
|
}
|
||||||
T value(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &defaultValue) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
T value(const K &key, const T &defaultValue) const noexcept
|
||||||
{
|
{
|
||||||
if (auto *v = valueImpl(key))
|
if (auto *v = valueImpl(key))
|
||||||
return *v;
|
return *v;
|
||||||
else
|
else
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
T &operator[](const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
T &operator[](const K &key)
|
||||||
{
|
{
|
||||||
return operatorIndexImpl(key);
|
return operatorIndexImpl(key);
|
||||||
}
|
}
|
||||||
const T operator[](const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
const T operator[](const K &key) const noexcept
|
||||||
{
|
{
|
||||||
return value(key);
|
return value(key);
|
||||||
}
|
}
|
||||||
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
std::pair<iterator, iterator>
|
std::pair<iterator, iterator>
|
||||||
equal_range(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
equal_range(const K &key)
|
||||||
{
|
{
|
||||||
return equal_range_impl(*this, key);
|
return equal_range_impl(*this, key);
|
||||||
}
|
}
|
||||||
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
std::pair<const_iterator, const_iterator>
|
std::pair<const_iterator, const_iterator>
|
||||||
equal_range(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
equal_range(const K &key) const noexcept
|
||||||
{
|
{
|
||||||
return equal_range_impl(*this, key);
|
return equal_range_impl(*this, key);
|
||||||
}
|
}
|
||||||
iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
iterator find(const K &key)
|
||||||
{
|
{
|
||||||
return findImpl(key);
|
return findImpl(key);
|
||||||
}
|
}
|
||||||
const_iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
const_iterator find(const K &key) const noexcept
|
||||||
{
|
{
|
||||||
return constFindImpl(key);
|
return constFindImpl(key);
|
||||||
}
|
}
|
||||||
const_iterator constFind(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
const_iterator constFind(const K &key) const noexcept
|
||||||
{
|
{
|
||||||
return find(key);
|
return find(key);
|
||||||
}
|
}
|
||||||
#endif // __cpp_concepts
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2372,99 +2386,120 @@ private:
|
|||||||
return iterator(result.it);
|
return iterator(result.it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename K>
|
||||||
|
using if_heterogeneously_seachable = QHashPrivate::if_heterogeneously_seachable_with<Key, K>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef __cpp_concepts
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
qsizetype remove(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
qsizetype remove(const K &key)
|
||||||
{
|
{
|
||||||
return removeImpl(key);
|
return removeImpl(key);
|
||||||
}
|
}
|
||||||
T take(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
T take(const K &key)
|
||||||
{
|
{
|
||||||
return takeImpl(key);
|
return takeImpl(key);
|
||||||
}
|
}
|
||||||
bool contains(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
bool contains(const K &key) const noexcept
|
||||||
{
|
{
|
||||||
if (!d)
|
if (!d)
|
||||||
return false;
|
return false;
|
||||||
return d->findNode(key) != nullptr;
|
return d->findNode(key) != nullptr;
|
||||||
}
|
}
|
||||||
T value(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
T value(const K &key) const noexcept
|
||||||
{
|
{
|
||||||
if (auto *v = valueImpl(key))
|
if (auto *v = valueImpl(key))
|
||||||
return *v;
|
return *v;
|
||||||
else
|
else
|
||||||
return T();
|
return T();
|
||||||
}
|
}
|
||||||
T value(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &defaultValue) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
T value(const K &key, const T &defaultValue) const noexcept
|
||||||
{
|
{
|
||||||
if (auto *v = valueImpl(key))
|
if (auto *v = valueImpl(key))
|
||||||
return *v;
|
return *v;
|
||||||
else
|
else
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
T &operator[](const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
T &operator[](const K &key)
|
||||||
{
|
{
|
||||||
return operatorIndexImpl(key);
|
return operatorIndexImpl(key);
|
||||||
}
|
}
|
||||||
const T operator[](const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
const T operator[](const K &key) const noexcept
|
||||||
{
|
{
|
||||||
return value(key);
|
return value(key);
|
||||||
}
|
}
|
||||||
QList<T> values(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
QList<T> values(const K &key)
|
||||||
{
|
{
|
||||||
return valuesImpl(key);
|
return valuesImpl(key);
|
||||||
}
|
}
|
||||||
iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
iterator find(const K &key)
|
||||||
{
|
{
|
||||||
return findImpl(key);
|
return findImpl(key);
|
||||||
}
|
}
|
||||||
const_iterator constFind(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
const_iterator constFind(const K &key) const noexcept
|
||||||
{
|
{
|
||||||
return constFindImpl(key);
|
return constFindImpl(key);
|
||||||
}
|
}
|
||||||
const_iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
const_iterator find(const K &key) const noexcept
|
||||||
{
|
{
|
||||||
return constFindImpl(key);
|
return constFindImpl(key);
|
||||||
}
|
}
|
||||||
bool contains(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
bool contains(const K &key, const T &value) const noexcept
|
||||||
{
|
{
|
||||||
return containsImpl(key, value);
|
return containsImpl(key, value);
|
||||||
}
|
}
|
||||||
qsizetype remove(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value)
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
qsizetype remove(const K &key, const T &value)
|
||||||
{
|
{
|
||||||
return removeImpl(key, value);
|
return removeImpl(key, value);
|
||||||
}
|
}
|
||||||
qsizetype count(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
qsizetype count(const K &key) const noexcept
|
||||||
{
|
{
|
||||||
return countImpl(key);
|
return countImpl(key);
|
||||||
}
|
}
|
||||||
qsizetype count(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
qsizetype count(const K &key, const T &value) const noexcept
|
||||||
{
|
{
|
||||||
return countImpl(key, value);
|
return countImpl(key, value);
|
||||||
}
|
}
|
||||||
iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value)
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
iterator find(const K &key, const T &value)
|
||||||
{
|
{
|
||||||
return findImpl(key, value);
|
return findImpl(key, value);
|
||||||
}
|
}
|
||||||
const_iterator constFind(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
const_iterator constFind(const K &key, const T &value) const noexcept
|
||||||
{
|
{
|
||||||
return constFindImpl(key, value);
|
return constFindImpl(key, value);
|
||||||
}
|
}
|
||||||
const_iterator find(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key, const T &value) const noexcept
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
|
const_iterator find(const K &key, const T &value) const noexcept
|
||||||
{
|
{
|
||||||
return constFind(key, value);
|
return constFind(key, value);
|
||||||
}
|
}
|
||||||
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
std::pair<iterator, iterator>
|
std::pair<iterator, iterator>
|
||||||
equal_range(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key)
|
equal_range(const K &key)
|
||||||
{
|
{
|
||||||
return equal_range_impl(key);
|
return equal_range_impl(key);
|
||||||
}
|
}
|
||||||
|
template <typename K, if_heterogeneously_seachable<K> = true>
|
||||||
std::pair<const_iterator, const_iterator>
|
std::pair<const_iterator, const_iterator>
|
||||||
equal_range(const QHashPrivate::HeterogeneouslySearchableWith<Key> auto &key) const noexcept
|
equal_range(const K &key) const noexcept
|
||||||
{
|
{
|
||||||
return equal_range_impl(key);
|
return equal_range_impl(key);
|
||||||
}
|
}
|
||||||
#endif // __cpp_concepts
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(Hash)
|
Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(Hash)
|
||||||
|
@ -9,9 +9,6 @@
|
|||||||
#include <QtCore/qstring.h>
|
#include <QtCore/qstring.h>
|
||||||
#include <QtCore/qstringfwd.h>
|
#include <QtCore/qstringfwd.h>
|
||||||
|
|
||||||
#ifdef __cpp_concepts
|
|
||||||
#include <concepts>
|
|
||||||
#endif
|
|
||||||
#include <numeric> // for std::accumulate
|
#include <numeric> // for std::accumulate
|
||||||
#include <functional> // for std::hash
|
#include <functional> // for std::hash
|
||||||
#include <utility> // For std::pair
|
#include <utility> // For std::pair
|
||||||
@ -238,19 +235,44 @@ size_t qHash(const T &t, size_t seed, Args&&...) noexcept(noexcept(qHash(t)))
|
|||||||
#endif // < Qt 7
|
#endif // < Qt 7
|
||||||
|
|
||||||
namespace QHashPrivate {
|
namespace QHashPrivate {
|
||||||
#ifdef __cpp_concepts
|
|
||||||
template <typename Key, typename T> concept HeterogeneouslySearchableWithHelper =
|
namespace detail {
|
||||||
|
// approximates std::equality_comparable_with
|
||||||
|
template <typename T, typename U, typename = void>
|
||||||
|
struct is_equality_comparable_with : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct is_equality_comparable_with<T, U,
|
||||||
|
std::void_t<
|
||||||
|
decltype(bool(std::declval<T>() == std::declval<U>())),
|
||||||
|
decltype(bool(std::declval<U>() == std::declval<T>())),
|
||||||
|
decltype(bool(std::declval<T>() != std::declval<U>())),
|
||||||
|
decltype(bool(std::declval<U>() != std::declval<T>()))
|
||||||
|
>>
|
||||||
|
: std::true_type {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename T> struct HeterogeneouslySearchableWithHelper
|
||||||
|
: std::conjunction<
|
||||||
// if Key and T are not the same (member already exists)
|
// if Key and T are not the same (member already exists)
|
||||||
!std::is_same_v<Key, T>
|
std::negation<std::is_same<Key, T>>,
|
||||||
// but are comparable amongst each other
|
// but are comparable amongst each other
|
||||||
&& std::equality_comparable_with<Key, T>
|
detail::is_equality_comparable_with<Key, T>,
|
||||||
// and supports heteregenous hashing
|
// and supports heteregenous hashing
|
||||||
&& QHashHeterogeneousSearch<Key, T>::value;
|
QHashHeterogeneousSearch<Key, T>
|
||||||
template <typename Key, typename T> concept HeterogeneouslySearchableWith =
|
> {};
|
||||||
HeterogeneouslySearchableWithHelper<q20::remove_cvref_t<Key>, q20::remove_cvref_t<T>>;
|
|
||||||
#else
|
template <typename Key, typename T>
|
||||||
template <typename Key, typename T> constexpr bool HeterogeneouslySearchableWith = false;
|
using HeterogeneouslySearchableWith = HeterogeneouslySearchableWithHelper<
|
||||||
#endif
|
q20::remove_cvref_t<Key>,
|
||||||
|
q20::remove_cvref_t<T>
|
||||||
|
>;
|
||||||
|
|
||||||
|
template <typename Key, typename K>
|
||||||
|
using if_heterogeneously_seachable_with = std::enable_if_t<
|
||||||
|
QHashPrivate::HeterogeneouslySearchableWith<Key, K>::value,
|
||||||
|
bool>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -259,9 +281,8 @@ bool qHashEquals(const T &a, const T &b)
|
|||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2, QHashPrivate::if_heterogeneously_seachable_with<T1, T2> = true>
|
||||||
std::enable_if_t<QHashPrivate::HeterogeneouslySearchableWith<T1, T2>, bool>
|
bool qHashEquals(const T1 &a, const T2 &b)
|
||||||
qHashEquals(const T1 &a, const T2 &b)
|
|
||||||
{
|
{
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
|
@ -1169,9 +1169,12 @@ void tst_QHash::operator_eq()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cpp_concepts
|
|
||||||
struct HeterogeneousHashingType
|
struct HeterogeneousHashingType
|
||||||
{
|
{
|
||||||
|
#ifndef __cpp_aggregate_paren_init
|
||||||
|
HeterogeneousHashingType() = default;
|
||||||
|
HeterogeneousHashingType(const QString &string) : s(string) {}
|
||||||
|
#endif
|
||||||
inline static int conversionCount = 0;
|
inline static int conversionCount = 0;
|
||||||
QString s;
|
QString s;
|
||||||
|
|
||||||
@ -1182,12 +1185,18 @@ struct HeterogeneousHashingType
|
|||||||
}
|
}
|
||||||
|
|
||||||
// std::equality_comparable_with requires we be self-comparable too
|
// std::equality_comparable_with requires we be self-comparable too
|
||||||
friend bool operator==(const HeterogeneousHashingType &t1, const HeterogeneousHashingType &t2) = default;
|
friend bool operator==(const HeterogeneousHashingType &t1, const HeterogeneousHashingType &t2) { return t1.s == t2.s; };
|
||||||
|
|
||||||
friend bool operator==(const QString &string, const HeterogeneousHashingType &tester)
|
friend bool operator==(const QString &string, const HeterogeneousHashingType &tester)
|
||||||
{ return tester.s == string; }
|
{ return tester.s == string; }
|
||||||
|
#ifndef __cpp_impl_three_way_compare // full set required for detail::is_equality_comparable_with<QString>
|
||||||
friend bool operator!=(const QString &string, const HeterogeneousHashingType &tester)
|
friend bool operator!=(const QString &string, const HeterogeneousHashingType &tester)
|
||||||
{ return !(tester.s == string); }
|
{ return !operator==(string, tester); }
|
||||||
|
friend bool operator==(const HeterogeneousHashingType &tester, const QString &string)
|
||||||
|
{ return operator==(string, tester); }
|
||||||
|
friend bool operator!=(const HeterogeneousHashingType &tester, const QString &string)
|
||||||
|
{ return !operator==(string, tester); }
|
||||||
|
#endif
|
||||||
|
|
||||||
friend size_t qHash(const HeterogeneousHashingType &tester, size_t seed)
|
friend size_t qHash(const HeterogeneousHashingType &tester, size_t seed)
|
||||||
{ return qHash(tester.s, seed); }
|
{ return qHash(tester.s, seed); }
|
||||||
@ -1196,10 +1205,9 @@ QT_BEGIN_NAMESPACE
|
|||||||
template <> struct QHashHeterogeneousSearch<QString, HeterogeneousHashingType> : std::true_type {};
|
template <> struct QHashHeterogeneousSearch<QString, HeterogeneousHashingType> : std::true_type {};
|
||||||
template <> struct QHashHeterogeneousSearch<HeterogeneousHashingType, QString> : std::true_type {};
|
template <> struct QHashHeterogeneousSearch<HeterogeneousHashingType, QString> : std::true_type {};
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
static_assert(std::is_same_v<QString, std::common_type_t<QString, HeterogeneousHashingType>>);
|
static_assert(QHashPrivate::detail::is_equality_comparable_with<QString, HeterogeneousHashingType>::value);
|
||||||
static_assert(std::equality_comparable_with<QString, HeterogeneousHashingType>);
|
static_assert(QHashPrivate::HeterogeneouslySearchableWith<QString, HeterogeneousHashingType>::value);
|
||||||
static_assert(QHashPrivate::HeterogeneouslySearchableWith<QString, HeterogeneousHashingType>);
|
static_assert(QHashPrivate::HeterogeneouslySearchableWith<HeterogeneousHashingType, QString>::value);
|
||||||
static_assert(QHashPrivate::HeterogeneouslySearchableWith<HeterogeneousHashingType, QString>);
|
|
||||||
|
|
||||||
template <typename T> struct HeterogeneousSearchTestHelper
|
template <typename T> struct HeterogeneousSearchTestHelper
|
||||||
{
|
{
|
||||||
@ -1219,14 +1227,10 @@ template <> struct HeterogeneousSearchTestHelper<HeterogeneousHashingType>
|
|||||||
QCOMPARE(HeterogeneousHashingType::conversionCount, 0);
|
QCOMPARE(HeterogeneousHashingType::conversionCount, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#else
|
|
||||||
using HeterogeneousHashingType = QString;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <template <typename, typename> class Hash, typename String, typename View, typename Converter>
|
template <template <typename, typename> class Hash, typename String, typename View, typename Converter>
|
||||||
static void heterogeneousSearchTest(const QList<std::remove_const_t<String>> &keys, Converter conv)
|
static void heterogeneousSearchTest(const QList<std::remove_const_t<String>> &keys, Converter conv)
|
||||||
{
|
{
|
||||||
#ifdef __cpp_concepts
|
|
||||||
using Helper = HeterogeneousSearchTestHelper<View>;
|
using Helper = HeterogeneousSearchTestHelper<View>;
|
||||||
String key = keys.last();
|
String key = keys.last();
|
||||||
String otherKey = keys.first();
|
String otherKey = keys.first();
|
||||||
@ -1334,11 +1338,6 @@ static void heterogeneousSearchTest(const QList<std::remove_const_t<String>> &ke
|
|||||||
QCOMPARE_EQ(hash.find(keyView), hash.end());
|
QCOMPARE_EQ(hash.find(keyView), hash.end());
|
||||||
QCOMPARE_EQ(hash.constFind(keyView), hash.constEnd());
|
QCOMPARE_EQ(hash.constFind(keyView), hash.constEnd());
|
||||||
Helper::checkCounter();
|
Helper::checkCounter();
|
||||||
#else
|
|
||||||
Q_UNUSED(keys);
|
|
||||||
Q_UNUSED(conv);
|
|
||||||
QSKIP("This feature requires C++20 (concepts)");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <template <typename, typename> class Hash, typename String, typename View>
|
template <template <typename, typename> class Hash, typename String, typename View>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user