19#include "private/qglobal_p.h"
23#include <initializer_list>
33
34
35
36
37
38
39
40
41
42
43
52#ifndef QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
53# if QT_VERSION >= QT_VERSION_CHECK(6
, 5
, 0
)
54# define QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
65template <
class Key,
class T,
class Compare>
71 : Compare(key_compare)
75 using value_type =
std::pair<
const Key, T>;
77 std::declval<Compare>()(
std::declval<
const Key &>(),
std::declval<
const Key &>()));
79 bool operator()(
const value_type &lhs,
const value_type &rhs)
const
82 return Compare::operator()(lhs.first, rhs.first);
106template<
class Key,
class T,
class Compare =
std::less<Key>,
class KeyContainer =
QList<Key>,
107 class MappedContainer =
QList<T>>
110 static_assert(
std::is_nothrow_destructible_v<T>,
"Types with throwing destructors are not supported in Qt containers.");
116 using key_type = Key;
117 using mapped_type = T;
119 using value_type =
typename value_compare::value_type;
120 using key_container_type = KeyContainer;
121 using mapped_container_type = MappedContainer;
122 using size_type =
typename key_container_type::size_type;
123 using key_compare = Compare;
135 using value_type =
std::pair<
const Key, T>;
136 using reference =
std::pair<
const Key &, T &>;
138 using iterator_category =
std::random_access_iterator_tag;
149 return { c->keys[i], c->values[i] };
159 return c == o.c && i == o.i;
231 return { c->keys[k], c->values[k] };
254 const Key &
key()
const {
return c->keys[i]; }
255 T &
value()
const {
return c->values[i]; }
267 using value_type =
std::pair<
const Key,
const T>;
268 using reference =
std::pair<
const Key &,
const T &>;
270 using iterator_category =
std::random_access_iterator_tag;
286 return { c->keys[i], c->values[i] };
296 return c == o.c && i == o.i;
368 return { c->keys[k], c->values[k] };
391 const Key &
key()
const {
return c->keys[i]; }
392 const T &
value()
const {
return c->values[i]; }
401 template <
class,
class =
void>
402 struct is_marked_transparent_type : std::false_type { };
411 template <
typename It>
418#ifdef QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
457 const mapped_container_type &values)
463 const mapped_container_type &values)
464 : c{
std::move(keys), values}
469 mapped_container_type &&values)
470 : c{keys,
std::move(values)}
475 mapped_container_type &&values)
476 : c{
std::move(keys),
std::move(values)}
485 template <
class InputIt, is_compatible_iterator<InputIt> =
nullptr>
488 initWithRange(first, last);
492 : value_compare(compare)
496#ifdef QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
540 const mapped_container_type &values,
const Compare &compare)
541 : value_compare(compare), c{keys, values}
546 const mapped_container_type &values,
const Compare &compare)
547 : value_compare(compare), c{
std::move(keys), values}
552 mapped_container_type &&values,
const Compare &compare)
553 : value_compare(compare), c{keys,
std::move(values)}
558 mapped_container_type &&values,
const Compare &compare)
559 : value_compare(compare), c{
std::move(keys),
std::move(values)}
564 const Compare &compare)
569 template <
class InputIt, is_compatible_iterator<InputIt> =
nullptr>
571 : value_compare(compare)
573 initWithRange(first, last);
576 size_type
count()
const noexcept {
return c.keys.size(); }
577 size_type
size()
const noexcept {
return c.keys.size(); }
578 size_type
capacity()
const noexcept {
return c.keys.capacity(); }
579 bool isEmpty()
const noexcept {
return c.keys.empty(); }
580 bool empty()
const noexcept {
return c.keys.empty(); }
582 const key_container_type &
keys()
const noexcept {
return c.keys; }
583 const mapped_container_type &
values()
const noexcept {
return c.values; }
599 return do_remove(find(key));
602 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
605 return do_remove(find(key));
610 c.values.erase(toValuesIterator(it));
611 return fromKeysIterator(c.keys.erase(toKeysIterator(it)));
616 return do_take(find(key));
619 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
622 return do_take(find(key));
627 return find(key) != end();
630 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
633 return find(key) != end();
636 T
value(
const Key &key,
const T &defaultValue)
const
639 return it == end() ? defaultValue : it.value();
642 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
643 T
value(
const X &key,
const T &defaultValue)
const
646 return it == end() ? defaultValue : it.value();
652 return it == end() ? T() : it.value();
655 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
659 return it == end() ? T() : it.value();
664 return try_emplace(key).first.value();
669 return try_emplace(
std::move(key)).first.value();
677#ifdef QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
699 template <
typename...Args>
702 auto it = lower_bound(key);
703 if (it == end() || key_compare::operator()(key, it.key())) {
704 c.values.emplace(toValuesIterator(it),
std::forward<Args>(args)...);
705 return { fromKeysIterator(c.keys.insert(toKeysIterator(it), key)),
true };
711 template <
typename...Args>
714 auto it = lower_bound(key);
715 if (it == end() || key_compare::operator()(key, it.key())) {
716 c.values.emplace(toValuesIterator(it),
std::forward<Args>(args)...);
717 return { fromKeysIterator(c.keys.insert(toKeysIterator(it),
std::move(key))),
true };
723 template <
typename M>
726 auto r = try_emplace(key,
std::forward<M>(obj));
728 *toValuesIterator(r.first) =
std::forward<M>(obj);
732 template <
typename M>
735 auto r = try_emplace(
std::move(key),
std::forward<M>(obj));
737 *toValuesIterator(r.first) =
std::forward<M>(obj);
741#ifdef QFLATMAP_ENABLE_STL_COMPATIBLE_INSERT
794 auto cit =
std::as_const(*
this).lower_bound(key);
795 return { &c, cit.i };
798 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
801 auto cit =
std::as_const(*
this).lower_bound(key);
802 return { &c, cit.i };
807 return fromKeysIterator(
std::lower_bound(c.keys.begin(), c.keys.end(), key,
key_comp()));
810 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
813 return fromKeysIterator(
std::lower_bound(c.keys.begin(), c.keys.end(), key,
key_comp()));
818 return { &c,
std::as_const(*
this).find(key).i };
821 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
824 return { &c,
std::as_const(*
this).find(key).i };
829 auto it = lower_bound(key);
831 if (!key_compare::operator()(key, it.key()))
838 template <
class X,
class Y = Compare, is_marked_transparent<Y> =
nullptr>
841 auto it = lower_bound(key);
843 if (!key_compare::operator()(key, it.key()))
850 template <
typename Predicate>
853 const auto indirect_call_to_pred = [pred =
std::move(pred)](
iterator it) {
854 using Pair =
decltype(*it);
855 using K =
decltype(it.key());
856 using V =
decltype(it.value());
858 if constexpr (
std::is_invocable_v<P, K, V>) {
859 return pred(it.key(), it.value());
860 }
else if constexpr (
std::is_invocable_v<P, Pair> && !
std::is_invocable_v<P, K>) {
862 }
else if constexpr (
std::is_invocable_v<P, K> && !
std::is_invocable_v<P, Pair>) {
863 return pred(it.key());
865 static_assert(QtPrivate::type_dependent_false<Predicate>(),
866 "Don't know how to call the predicate.\n"
869 "- pred(it.key(), it.value())\n"
874 auto first = begin();
875 const auto last = end();
878 while (first != last && !indirect_call_to_pred(first))
886 auto kdest = toKeysIterator(first);
887 auto vdest = toValuesIterator(first);
891 auto k =
std::next(kdest);
892 auto v =
std::next(vdest);
905 while (first != last) {
906 if (!indirect_call_to_pred(first)) {
908 *kdest =
std::move(*k);
909 *vdest =
std::move(*v);
918 const size_type r =
std::distance(kdest, c.keys.end());
919 c.keys.erase(kdest, c.keys.end());
920 c.values.erase(vdest, c.values.end());
926 return static_cast<key_compare>(*
this);
931 return static_cast<value_compare>(*
this);
947 T result =
std::move(it.value());
954 template <
class InputIt, is_compatible_iterator<InputIt> =
nullptr>
955 void initWithRange(InputIt first, InputIt last)
957 QtPrivate::reserveIfForwardIterator(
this, first, last);
958 while (first != last) {
959 c.keys.push_back(first->first);
960 c.values.push_back(first->second);
965 iterator fromKeysIterator(
typename key_container_type::iterator kit)
967 return { &c,
static_cast<size_type>(
std::distance(c.keys.begin(), kit)) };
970 const_iterator fromKeysIterator(
typename key_container_type::const_iterator kit)
const
972 return { &c,
static_cast<size_type>(
std::distance(c.keys.begin(), kit)) };
975 typename key_container_type::iterator toKeysIterator(
iterator it)
977 return c.keys.begin() + it.i;
980 typename mapped_container_type::iterator toValuesIterator(
iterator it)
982 return c.values.begin() + it.i;
985 template <
class InputIt>
986 void insertRange(InputIt first, InputIt last)
988 size_type i = c.keys.size();
989 c.keys.resize(i +
std::distance(first, last));
990 c.values.resize(c.keys.size());
991 for (; first != last; ++first, ++i) {
992 c.keys[i] = first->first;
993 c.values[i] = first->second;
995 ensureOrderedUnique();
998 class IndexedKeyComparator
1001 IndexedKeyComparator(
const QFlatMap *am)
1006 bool operator()(size_type i, size_type k)
const
1015 template <
class InputIt>
1016 void insertOrderedUniqueRange(InputIt first, InputIt last)
1018 const size_type s = c.keys.size();
1019 c.keys.resize(s +
std::distance(first, last));
1020 c.values.resize(c.keys.size());
1021 for (size_type i = s; first != last; ++first, ++i) {
1022 c.keys[i] = first->first;
1023 c.values[i] = first->second;
1026 std::vector<size_type> p(size_t(c.keys.size()));
1027 std::iota(p.begin(), p.end(), 0);
1028 std::inplace_merge(p.begin(), p.begin() + s, p.end(), IndexedKeyComparator(
this));
1029 applyPermutation(p);
1033 void ensureOrderedUnique()
1035 std::vector<size_type> p(size_t(c.keys.size()));
1036 std::iota(p.begin(), p.end(), 0);
1037 std::stable_sort(p.begin(), p.end(), IndexedKeyComparator(
this));
1038 applyPermutation(p);
1042 void applyPermutation(
const std::vector<size_type> &p)
1044 const size_type s = c.keys.size();
1045 std::vector<
bool> done(s);
1046 for (size_type i = 0; i < s; ++i) {
1053 qSwap(c.keys[j], c.keys[k]);
1054 qSwap(c.values[j], c.values[k]);
1065 auto equivalent = [
this](
const auto &lhs,
const auto &rhs) {
1066 return !key_compare::operator()(lhs, rhs) && !key_compare::operator()(rhs, lhs);
1068 const auto kb = c.keys.begin();
1069 const auto ke = c.keys.end();
1070 auto k =
std::adjacent_find(kb, ke, equivalent);
1075 auto v =
std::next(c.values.begin(),
std::distance(kb, k));
1088 while ((++v, ++k) != ke) {
1089 if (!equivalent(*kdest, *k)) {
1090 *++kdest =
std::move(*k);
1091 *++vdest =
std::move(*v);
1095 c.keys.erase(
std::next(kdest), ke);
1096 c.values.erase(
std::next(vdest), c.values.end());
1102template <
class Key,
class T,
1103 qsizetype N = QVarLengthArrayDefaultPrealloc,
1104 class Compare = std::less<Key>>
1105using 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)
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)
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)
friend const_iterator operator-(const const_iterator a, size_type n)
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)
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
bool operator<=(const iterator &other) const
bool operator!=(const iterator &o) const
friend iterator operator+(const iterator a, size_type n)
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
size_type count() const noexcept
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
QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys, const mapped_container_type &values, const Compare &compare)
QFlatMap(const Compare &compare)
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
bool contains(const Key &key) const
const_iterator find(const Key &key) const
T value(const X &key) const
std::reverse_iterator< iterator > rbegin()
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
T value(const X &key, const T &defaultValue) const
size_type remove_if(Predicate pred)
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
const_iterator constEnd() const
QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys, mapped_container_type &&values, const Compare &compare)
QFlatMap(Qt::OrderedUniqueRange_t, std::initializer_list< value_type > lst)
const mapped_container_type & values() const noexcept
const_iterator find(const X &key) const
void reserve(size_type s)
QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys, mapped_container_type &&values)
iterator lower_bound(const X &key)
QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys, const mapped_container_type &values)
T value(const Key &key, const T &defaultValue) const
bool remove(const X &key)
std::reverse_iterator< iterator > rend()
std::pair< iterator, bool > try_emplace(Key &&key, Args &&...args)
const_iterator end() const
std::pair< iterator, bool > try_emplace(const Key &key, Args &&...args)
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(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(Qt::OrderedUniqueRange_t, InputIt first, InputIt last, const Compare &compare)
constexpr OrderedUniqueRange_t OrderedUniqueRange
mapped_container_type values