19#include <QtCore/qcontainertools_impl.h>
21#include <QtCore/qtclasshelpermacros.h>
22#include "private/qglobal_p.h"
26#include <initializer_list>
36
37
38
39
40
41
42
43
44
45
46
54template <
class Key,
class T,
class Compare>
60 : Compare(key_compare)
66 std::declval<Compare>()(
std::declval<
const Key &>(),
std::declval<
const Key &>()));
71 return Compare::operator()(lhs.first, rhs.first);
75template<
class Key,
class T,
class Compare =
std::less<Key>,
class KeyContainer =
QList<Key>,
76 class MappedContainer =
QList<T>>
79 static_assert(
std::is_nothrow_destructible_v<T>,
"Types with throwing destructors are not supported in Qt containers.");
114 return { c->keys[i], c->values[i] };
124 return c == o.c && i == o.i;
196 return { c->keys[k], c->values[k] };
219 const Key &
key()
const {
return c->keys[i]; }
220 T &
value()
const {
return c->values[i]; }
251 return { c->keys[i], c->values[i] };
261 return c == o.c && i == o.i;
333 return { c->keys[k], c->values[k] };
356 const Key &
key()
const {
return c->keys[i]; }
357 const T &
value()
const {
return c->values[i]; }
366 template <
class,
class =
void>
367 struct is_marked_transparent_type : std::false_type { };
376 template <
typename It>
386 ensureOrderedUnique();
390 : c{
std::move(keys), values}
392 ensureOrderedUnique();
396 : c{keys,
std::move(values)}
398 ensureOrderedUnique();
402 : c{
std::move(keys),
std::move(values)}
404 ensureOrderedUnique();
412 template <
class InputIt, is_compatible_iterator<InputIt> =
nullptr>
415 initWithRange(first, last);
416 ensureOrderedUnique();
427 : c{
std::move(keys), values}
433 : c{keys,
std::move(values)}
439 : c{
std::move(keys),
std::move(values)}
444 :
QFlatMap(Qt::OrderedUniqueRange, lst.begin(), lst.end())
448 template <
class InputIt, is_compatible_iterator<InputIt> =
nullptr>
451 initWithRange(first, last);
460 const Compare &compare)
463 ensureOrderedUnique();
467 const Compare &compare)
470 ensureOrderedUnique();
474 const Compare &compare)
477 ensureOrderedUnique();
481 const Compare &compare)
484 ensureOrderedUnique();
488 :
QFlatMap(lst.begin(), lst.end(), compare)
492 template <
class InputIt, is_compatible_iterator<InputIt> =
nullptr>
493 explicit QFlatMap(InputIt first, InputIt last,
const Compare &compare)
496 initWithRange(first, last);
497 ensureOrderedUnique();
525 const Compare &compare)
526 :
QFlatMap(Qt::OrderedUniqueRange, lst.begin(), lst.end(), compare)
530 template <
class InputIt, is_compatible_iterator<InputIt> =
nullptr>
534 initWithRange(first, last);
540 bool isEmpty()
const noexcept {
return c.keys.empty(); }
541 bool empty()
const noexcept {
return c.keys.empty(); }
560 return do_remove(find(key));
563 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
566 return do_remove(find(key));
571 c.values.erase(toValuesIterator(it));
572 return fromKeysIterator(c.keys.erase(toKeysIterator(it)));
577 return do_take(find(key));
580 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
583 return do_take(find(key));
588 return find(key) != end();
591 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
594 return find(key) != end();
597 T
value(
const Key &key,
const T &defaultValue)
const
600 return it == end() ? defaultValue : it.value();
603 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
604 T
value(
const X &key,
const T &defaultValue)
const
607 return it == end() ? defaultValue : it.value();
618 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
629 return try_emplace(key).first.value();
634 return try_emplace(
std::move(key)).first.value();
644 return try_emplace(key, value);
649 return try_emplace(
std::move(key), value);
654 return try_emplace(key,
std::move(value));
659 return try_emplace(
std::move(key),
std::move(value));
662 template <
typename...Args>
665 auto it = lower_bound(key);
666 if (it == end() ||
key_compare::operator()(key, it.key())) {
667 c.values.emplace(toValuesIterator(it),
std::forward<Args>(args)...);
668 return { fromKeysIterator(c.keys.insert(toKeysIterator(it), key)),
true };
674 template <
typename...Args>
677 auto it = lower_bound(key);
678 if (it == end() ||
key_compare::operator()(key, it.key())) {
679 c.values.emplace(toValuesIterator(it),
std::forward<Args>(args)...);
680 return { fromKeysIterator(c.keys.insert(toKeysIterator(it),
std::move(key))),
true };
686 template <
typename M>
689 auto r = try_emplace(key,
std::forward<M>(obj));
691 *toValuesIterator(r.first) =
std::forward<M>(obj);
695 template <
typename M>
698 auto r = try_emplace(
std::move(key),
std::forward<M>(obj));
700 *toValuesIterator(r.first) =
std::forward<M>(obj);
704 template <
class InputIt, is_compatible_iterator<InputIt> =
nullptr>
707 insertRange(first, last);
714 insertRange(first, last);
717 template <
class InputIt, is_compatible_iterator<InputIt> =
nullptr>
720 insertOrderedUniqueRange(first, last);
727 insertOrderedUniqueRange(first, last);
755 auto cit =
std::as_const(*
this).lower_bound(key);
756 return { &c, cit.i };
759 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
762 auto cit =
std::as_const(*
this).lower_bound(key);
763 return { &c, cit.i };
768 return fromKeysIterator(
std::lower_bound(c.keys.begin(), c.keys.end(), key,
key_comp()));
771 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
774 return fromKeysIterator(
std::lower_bound(c.keys.begin(), c.keys.end(), key,
key_comp()));
779 return { &c,
std::as_const(*
this).find(key).i };
782 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
785 return { &c,
std::as_const(*
this).find(key).i };
790 auto it = lower_bound(key);
799 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
802 auto it = lower_bound(key);
811 template <
typename Predicate>
814 const auto indirect_call_to_pred = [pred =
std::move(pred)](
iterator it) {
815 using Pair =
decltype(*it);
816 using K =
decltype(it.key());
817 using V =
decltype(it.value());
819 if constexpr (
std::is_invocable_v<P, K, V>) {
820 return pred(it.key(), it.value());
821 }
else if constexpr (
std::is_invocable_v<P, Pair> && !
std::is_invocable_v<P, K>) {
823 }
else if constexpr (
std::is_invocable_v<P, K> && !
std::is_invocable_v<P, Pair>) {
824 return pred(it.key());
826 static_assert(QtPrivate::type_dependent_false<Predicate>(),
827 "Don't know how to call the predicate.\n"
830 "- pred(it.key(), it.value())\n"
835 auto first = begin();
836 const auto last = end();
839 while (first != last && !indirect_call_to_pred(first))
847 auto kdest = toKeysIterator(first);
848 auto vdest = toValuesIterator(first);
852 auto k =
std::next(kdest);
853 auto v =
std::next(vdest);
866 while (first != last) {
867 if (!indirect_call_to_pred(first)) {
869 *kdest =
std::move(*k);
870 *vdest =
std::move(*v);
880 c.keys.erase(kdest, c.keys.end());
881 c.values.erase(vdest, c.values.end());
910 T result =
std::move(it.value());
916 template <
class InputIt, is_compatible_iterator<InputIt> =
nullptr>
917 void initWithRange(InputIt first, InputIt last)
919 QtPrivate::reserveIfForwardIterator(
this, first, last);
920 while (first != last) {
921 c.keys.push_back(first->first);
922 c.values.push_back(first->second);
929 return { &c,
static_cast<
size_type>(
std::distance(c.keys.begin(), kit)) };
934 return { &c,
static_cast<
size_type>(
std::distance(c.keys.begin(), kit)) };
939 return c.keys.begin() + it.i;
944 return c.values.begin() + it.i;
947 template <
class InputIt>
948 void insertRange(InputIt first, InputIt last)
951 c.keys.resize(i +
std::distance(first, last));
952 c.values.resize(c.keys.size());
953 for (; first != last; ++first, ++i) {
954 c.keys[i] = first->first;
955 c.values[i] = first->second;
957 ensureOrderedUnique();
960 class IndexedKeyComparator
963 IndexedKeyComparator(
const QFlatMap *am)
977 template <
class InputIt>
978 void insertOrderedUniqueRange(InputIt first, InputIt last)
981 c.keys.resize(s +
std::distance(first, last));
982 c.values.resize(c.keys.size());
983 for (
size_type i = s; first != last; ++first, ++i) {
984 c.keys[i] = first->first;
985 c.values[i] = first->second;
988 std::vector<size_type> p(size_t(c.keys.size()));
989 std::iota(p.begin(), p.end(), 0);
990 std::inplace_merge(p.begin(), p.begin() + s, p.end(), IndexedKeyComparator(
this));
995 void ensureOrderedUnique()
997 std::vector<size_type> p(size_t(c.keys.size()));
998 std::iota(p.begin(), p.end(), 0);
999 std::stable_sort(p.begin(), p.end(), IndexedKeyComparator(
this));
1000 applyPermutation(p);
1004 void applyPermutation(
const std::vector<size_type> &p)
1007 std::vector<
bool> done(s);
1015 qSwap(c.keys[j], c.keys[k]);
1016 qSwap(c.values[j], c.values[k]);
1027 auto equivalent = [
this](
const auto &lhs,
const auto &rhs) {
1030 const auto kb = c.keys.begin();
1031 const auto ke = c.keys.end();
1032 auto k =
std::adjacent_find(kb, ke, equivalent);
1037 auto v =
std::next(c.values.begin(),
std::distance(kb, k));
1050 while ((++v, ++k) != ke) {
1051 if (!equivalent(*kdest, *k)) {
1052 *++kdest =
std::move(*k);
1053 *++vdest =
std::move(*v);
1057 c.keys.erase(
std::next(kdest), ke);
1058 c.values.erase(
std::next(vdest), c.values.end());
1064template <
class Key,
class T,
1065 qsizetype N = QVarLengthArrayDefaultPrealloc,
1066 class Compare = std::less<Key>>
1067using QVarLengthFlatMap = QFlatMap<Key, T, Compare, QVarLengthArray<Key, N>, QVarLengthArray<T, N>>;
bool operator()(const value_type &lhs, const value_type &rhs) const noexcept(is_comparator_noexcept)
std::pair< const Key, T > value_type
QFlatMapValueCompare()=default
static constexpr bool is_comparator_noexcept
QFlatMapValueCompare(const Compare &key_compare)
bool operator>=(const const_iterator &other) const
friend const_iterator operator+(size_type n, const const_iterator a)
const_iterator(const containers *ac, size_type ai)
const_iterator & operator-=(size_type n)
const_iterator operator++(int)
bool operator>(const const_iterator &other) const
friend difference_type operator-(const const_iterator b, const const_iterator a)
const_iterator(iterator o)
std::random_access_iterator_tag iterator_category
reference operator*() const
const_iterator & operator++()
bool operator==(const const_iterator &o) const
reference operator[](size_type n) const
pointer operator->() const
bool operator<(const const_iterator &other) const
bool operator<=(const const_iterator &other) const
bool operator!=(const const_iterator &o) const
const_iterator & operator+=(size_type n)
std::pair< const Key, const T > value_type
friend const_iterator operator-(const const_iterator a, size_type n)
std::pair< const Key &, const T & > reference
friend const_iterator operator+(const const_iterator a, size_type n)
const_iterator & operator--()
const_iterator operator--(int)
iterator(containers *ac, size_type ai)
bool operator>(const iterator &other) const
reference operator[](size_type n) const
iterator & operator-=(size_type n)
std::random_access_iterator_tag iterator_category
friend iterator operator-(const iterator a, size_type n)
friend iterator operator+(size_type n, const iterator a)
pointer operator->() const
bool operator==(const iterator &o) const
reference operator*() const
bool operator>=(const iterator &other) const
bool operator<(const iterator &other) const
std::pair< const Key &, T & > reference
bool operator<=(const iterator &other) const
bool operator!=(const iterator &o) const
friend iterator operator+(const iterator a, size_type n)
std::pair< const Key, T > value_type
iterator & operator+=(size_type n)
friend difference_type operator-(const iterator b, const iterator a)
bool isEmpty() const noexcept
bool empty() const noexcept
QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys, const mapped_container_type &values, const Compare &compare)
QFlatMap(Qt::OrderedUniqueRange_t, InputIt first, InputIt last)
std::reverse_iterator< const_iterator > crend() const
QFlatMap(const key_container_type &keys, mapped_container_type &&values, const Compare &compare)
size_type count() const noexcept
QFlatMap(key_container_type &&keys, mapped_container_type &&values)
std::pair< iterator, bool > insert_or_assign(const Key &key, M &&obj)
T value(const Key &key) const
const_iterator lower_bound(const X &key) const
const_iterator begin() const
const_iterator lower_bound(const Key &key) const
std::reverse_iterator< const_iterator > rbegin() const
void insert(Qt::OrderedUniqueRange_t, const value_type *first, const value_type *last)
QFlatMapValueCompare< Key, T, Compare > value_compare
QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys, const mapped_container_type &values, const Compare &compare)
QFlatMap(const Compare &compare)
std::pair< iterator, bool > insert(Key &&key, T &&value)
std::reverse_iterator< const_iterator > crbegin() const
T & operator[](const Key &key)
key_compare key_comp() const noexcept
iterator find(const X &key)
bool contains(const X &key) const
std::pair< iterator, bool > insert(const Key &key, T &&value)
bool contains(const Key &key) const
const_iterator find(const Key &key) const
T value(const X &key) const
std::reverse_iterator< iterator > rbegin()
void insert(Qt::OrderedUniqueRange_t, InputIt first, InputIt last)
iterator erase(iterator it)
const_iterator cbegin() const
iterator lower_bound(const Key &key)
T & operator[](Key &&key)
const key_container_type & keys() const noexcept
typename key_container_type::size_type size_type
QFlatMap(key_container_type &&keys, const mapped_container_type &values)
T value(const X &key, const T &defaultValue) const
size_type remove_if(Predicate pred)
QFlatMap(key_container_type &&keys, const mapped_container_type &values, const Compare &compare)
QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys, mapped_container_type &&values)
const_iterator constBegin() const
iterator find(const Key &key)
QFlatMap(Qt::OrderedUniqueRange_t, std::initializer_list< value_type > lst, const Compare &compare)
bool remove(const Key &key)
const_iterator cend() const
QFlatMap(key_container_type &&keys, mapped_container_type &&values, const Compare &compare)
const_iterator constEnd() const
QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys, mapped_container_type &&values, const Compare &compare)
void insert(const value_type *first, const value_type *last)
typename value_compare::value_type value_type
QFlatMap(Qt::OrderedUniqueRange_t, std::initializer_list< value_type > lst)
QFlatMap(InputIt first, InputIt last)
const mapped_container_type & values() const noexcept
const_iterator find(const X &key) const
void reserve(size_type s)
QFlatMap(const key_container_type &keys, mapped_container_type &&values)
QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys, mapped_container_type &&values)
iterator lower_bound(const X &key)
KeyContainer key_container_type
std::pair< iterator, bool > insert(const Key &key, const T &value)
QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys, const mapped_container_type &values)
MappedContainer mapped_container_type
QFlatMap(InputIt first, InputIt last, const Compare &compare)
T value(const Key &key, const T &defaultValue) const
bool remove(const X &key)
std::reverse_iterator< iterator > rend()
QFlatMap(const key_container_type &keys, const mapped_container_type &values)
std::pair< iterator, bool > try_emplace(Key &&key, Args &&...args)
const_iterator end() const
void insert(InputIt first, InputIt last)
std::pair< iterator, bool > try_emplace(const Key &key, Args &&...args)
QFlatMap(const key_container_type &keys, const mapped_container_type &values, const Compare &compare)
value_compare value_comp() const noexcept
std::reverse_iterator< const_iterator > rend() const
size_type size() const noexcept
size_type capacity() const noexcept
T operator[](const Key &key) const
std::pair< iterator, bool > insert_or_assign(Key &&key, M &&obj)
QFlatMap(std::initializer_list< value_type > lst, const Compare &compare)
QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys, const mapped_container_type &values)
QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys, mapped_container_type &&values, const Compare &compare)
QFlatMap(std::initializer_list< value_type > lst)
QFlatMap(Qt::OrderedUniqueRange_t, InputIt first, InputIt last, const Compare &compare)
std::pair< iterator, bool > insert(Key &&key, const T &value)
QT_DEFINE_TAG(OrderedUniqueRange)
mapped_container_type values