QT6 源(25)篇二:阅读 QMap<key,T>以及源代码:a[ i ] 增改,value()查询,删 remove(),用 Qt里自己的特性即可,不必要用 STL 的同样式的接口成员函数

(8)

在这里插入图片描述

(9)本源代码来自于头文件 qmap . h , 本文件里也包含了未整理的 multimap 类的定义 ,但裁剪掉了

#ifndef QMAP_H
#define QMAP_H

#include <QtCore/qiterator.h>
#include <QtCore/qlist.h>
#include <QtCore/qrefcount.h>
#include <QtCore/qpair.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qshareddata_impl.h>

#include <functional>
#include <initializer_list>
#include <map>
#include <algorithm>

QT_BEGIN_NAMESPACE //说明本类定义于 Qt 的全局命名控件

// common code shared between QMap and QMultimap
template <typename AMap> //这是 QMap 与 QMultimap 的公用代码,似乎是处理数据的存储
class QMapData : public QSharedData //无官方注释
{
public:
    using            Map = AMap;
    using            Key = typename Map::key_type      ;
    using            T   = typename Map::mapped_type   ;
    using     value_type = typename Map::value_type    ;
    using      size_type = typename Map::size_type     ;
    using       iterator = typename Map::iterator      ;
    using const_iterator = typename Map::const_iterator;

    static_assert(std::is_nothrow_destructible_v<Key>,
                "Types with throwing destructors are not supported in "
                "Qt containers.");

    static_assert(std::is_nothrow_destructible_v<T>,
                "Types with throwing destructors are not supported in "
                "Qt containers.");

    Map m;

    QMapData() = default;

    explicit QMapData(const Map &  other) : m(     other      ) {}

    explicit QMapData(      Map && other) : m(std::move(other)) {}

    // used in remove(); copies from source all the values not matching key.
    // returns how many were NOT copied (removed).
    size_type copyIfNotEquivalentTo(const Map & source, const Key & key)
    {
        Q_ASSERT(m.empty());

        size_type result = 0;
        const auto & keyCompare = source.key_comp();

        const auto filter = [&result, & key, & keyCompare](const auto & v)
        {   //这里定义了一个 lamda 表达式作为函数,有不活列表与参数列表
            if (!keyCompare(key, v.first) && !keyCompare(v.first, key)) {
                // keys are equivalent (neither a<b nor b<a) => found it
                ++result;
                return true;
            }
            return false;
        };

        std::remove_copy_if(source.cbegin(), source.cend(),
                            std::inserter(m, m.end()),  filter);

        return result;
    }

    // used in key(T), count(Key, T), find(key, T), etc; returns a
    // comparator object suitable for algorithms with std::(multi)map
    // iterators.
    static auto valueIsEqualTo(const T & value) //又包含了 lamda表达式
    {
        return [& value](const auto & v) { return v.second == value; };
    }

    Key key(const T & value, const Key & defaultKey) const
    {
        auto i = std::find_if(m.cbegin(),
                              m.cend(),
                              valueIsEqualTo(value));
        if (i != m.cend())
            return i->first;

        return defaultKey;
    }

    QList<Key> keys() const
    {
        QList<Key> result;
        result.reserve(m.size());

        const auto extractKey = [](const auto &v) { return v.first; };

        std::transform(m.cbegin(),
                       m.cend(),
                       std::back_inserter(result),
                       extractKey);
        return result;
    }

    QList<Key> keys(const T & value) const
    {
        QList<Key> result;
        result.reserve(m.size());
        // no std::transform_if...
        for (const auto &v : m) {
            if (v.second == value)
                result.append(v.first);
        }
        result.shrink_to_fit();
        return result;
    }

    QList<T> values() const
    {
        QList<T> result;
        result.reserve(m.size());

        const auto extractValue = [](const auto &v) { return v.second; };

        std::transform(m.cbegin(),
                       m.cend(),
                       std::back_inserter(result),
                       extractValue);
        return result;
    }

    size_type count(const Key &key) const
    {
        return m.count(key);
    }

    // Used in erase. Allocates a new QMapData and copies, from this->m,
    // the elements not in the [first, last) range. The return contains
    // the new QMapData and an iterator in its map pointing at the first
    // element after the erase.
    struct EraseResult {
        QMapData * data;
        iterator     it;
    };

    EraseResult erase(const_iterator first, const_iterator last) const
    {
        EraseResult result;
        result.data = new QMapData;
        result.it = result.data->m.end();
        const auto newDataEnd = result.it;

        auto i = m.begin();
        const auto e = m.end();

        // copy over all the elements before first
        while (i != first) {
            result.it = result.data->m.insert(newDataEnd, *i);
            ++i;
        }

        // skip until last
        while (i != last)
            ++i;

        // copy from last to the end
        while (i != e) {
            result.data->m.insert(newDataEnd, *i);
            ++i;
        }

        if (result.it != newDataEnd)
            ++result.it;

        return result;
    }
}; //完结 class QMapData : public QSharedData

//
// QMap
//

/*
The QMap class is a template class that provides an associative array.

QMap<Key,T>是 Qt的通用容器类之一。它存储(键,值)对,并提供通过键快速查找的功能。
QMap 和 QHash 提供了非常相似的功能。区别如下:
    QHash 提供比 QMap 更快的平均查找速度。(请参见算法复杂度以获取详细信息。)
    在迭代 QHash 时,项的顺序是任意的。对于QMap,项总是按键排序.
QHash的关键类型必须提供operator==()和一个全局函数gHash(Key)。
QMap 的关键类型必须提供operator< ()来指定完全排序。
自Qt5.8.1版本起,即使底层的operator<()没有提供完全排序,使用指针类型作为键也是安全的。

举例: QMap<QString, int> map;
    map["one"] = 1; 等价于  map.insert("twelve", 12);

To look up a value, use operator[]() or value()。 查找操作

If there is no item with the specified key in the map,
these functions return a default-constructed value.
If you want to check whether the map contains a certain key, use contains()。

There is also a value() overload that uses its second argument as a
default value if there is no item with the specified key:
    int timeout = map.value("TIMEOUT", 30);

一般来说,我们建议您使用contains()和value()而不是operator []()来查找映射中的键。
这是因为如果映射中没有与相同键相同的项(除非映射是const),
则operator[]()会静默地将项插入映射中。例如,以下代码片段将在内存中创建1000个项:

    // WRONG 这是错误做法
    QMap<int, QWidget *> map;
    ...
    for (int i = 0; i < 1000; ++i) {
        if (map[i] == okButton)
            cout << "Found button at index " << i << Qt::endl;
    }

为了避免这个问题,请在上述代码中将map【i】替换为map.value(i)。
如果要浏览 QMap 中存储的所有(key, value)对,可以使用迭代器。
QMap 提供 Java 样式的迭代器(OMaplterator和 QMutableMaplterator)
    和    STL  样式的选代器(OMap::const iterator和 QMap::iterator)。

项目按升序键顺序遍历。
通常,QMap只允许每个键有一个值。
如果使用已经存在于QMap中的键调用insert()函数,则先前的值将被擦除。例如:

    map.insert("plenty",  100);
    map.insert("plenty", 2000);
    // map.value("plenty") == 2000

但是,您可以使用 QMultiMap 来存储每个键的多个值。
如果您想检索单个键的所有值,可使用 values(const Key & key)方法,该方法返回-个 QList<T>:

    QList<int> values = map.values("plenty");
    for (int i = 0; i < values.size(); ++i)
        cout << values.at(i) << Qt::endl;

另一种方法是调用 find()来获取第一个具有键的 STL风格的迭代器,并从那里开始迭代:

    QMap<QString, int>::iterator i = map.find("plenty");
    while (i != map.end() && i.key() == "plenty") {
        cout << i.value() << Qt::endl;
        ++i;
    }

If you only need to extract the values from a map (not the keys),
 you can also use foreach:

    QMap<QString, int> map;
    ...
    foreach (int value, map)
        cout << value << Qt::endl;

Items can be removed from the map in several ways.
One way is to call remove();
this will remove any item with the given key.
Another way is to use QMutableMapIterator::remove().
In addition, you can clear the entire map using clear().

QMap's key and value data types must be assignable data types.
This covers most data types you are likely to encounter,
but the compiler won't let you, for example, store a QWidget as a value;
instead, store a QWidget *.
In addition, QMap's key type must provide operator<().
QMap uses it to keep its items sorted,and assumes that two keys x and y
    are equivalent if neither x < y nor y < x is true.

*/

template <class Key, class T>  // <Key, Value>
class QMap //重点开始
{
    using Map     = std::map<Key, T>;
    using MapData = QMapData<Map>   ;

    QtPrivate::QExplicitlySharedDataPointerV2<MapData>  d; //本类的数据成员

    friend class QMultiMap<Key, T>; //友元类

public:
    using        key_type = Key;
    using     mapped_type = T  ;

    //typedef  QIntegerForSizeof<void *>::Signed  qptrdiff;
    using difference_type = qptrdiff ; // 64位有符号整数
    using       size_type = qsizetype; // 有符号整数
    //using  qsizetype = QIntegerForSizeof<std::size_t>::Signed;

    QMap() = default; //默认构造函数

    // implicitly generated special member functions are OK!

    void swap(QMap<Key, T> & other) noexcept {  d.swap(other.d); }

    QMap(std::initializer_list<std::pair<Key, T>> list)
    {
        for (auto & p : list)
            insert(p.first, p.second);
    }

    explicit QMap(const std::map<Key, T> &  other) //基于 STL库的有参构造函数
        : d(other.empty() ? nullptr : new MapData(other)) { }

    explicit QMap(      std::map<Key, T> && other) //基于 STL库的有参构造函数
        : d(other.empty() ? nullptr : new MapData(std::move(other))) { }

    std::map<Key, T> toStdMap() const & //把本类型转换为 STL库里的 map 类型
    {
        if (d)    return d->m;

        return {};
    }

    std::map<Key, T> toStdMap()       &&
    {
        if (d) {
            if (d.isShared())   return d->m           ;
            else                return std::move(d->m);
        }

        return {};
    }

#ifndef Q_CLANG_QDOC  //走此 if 分支是成立的
    template <typename AKey = Key, typename AT = T>
    friend  QTypeTraits::compare_eq_result_container<QMap, AKey, AT> //友元函数
    operator==(const QMap & lhs, const QMap & rhs) //定义了全局比较运算符函数 ==、!=
    {
        if (lhs.d == rhs.d)   return true;

        if (!lhs.d)           return rhs == lhs;

        Q_ASSERT(lhs.d);
        return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
    }

    template <typename AKey = Key, typename AT = T> // operator!=
    friend QTypeTraits::compare_eq_result_container<QMap, AKey, AT>
    operator!=(const QMap & lhs, const QMap & rhs) { return !(lhs == rhs); }

    // TODO: add the other comparison operators; std::map has them.
#else  // else 不成立
    friend bool operator==(const QMap &lhs, const QMap &rhs);
    friend bool operator!=(const QMap &lhs, const QMap &rhs);
#endif // Q_CLANG_QDOC

    //Returns the number of (key, value) pairs in the map.
    size_type size () const { return d ? size_type(d->m.size()) : size_type(0); }

    size_type count() const {  return size(); }  //Same as size().

    //Returns the number of items associated with key key.
    size_type count(const Key & key) const
    {
        if (!d)   return 0;

        return d->count(key);
    }

    bool isEmpty() const { return d ? d->m.empty() : true; }

    bool isDetached() const noexcept     //无注释, Qt 的隐式共享
    {   // false makes little sense, but that's shared_null's behavior...
        return d ? !d.isShared() : false;
    }

    void   detach() //无注释, Qt 的隐式共享
    {
        if (d)
            d.detach();
        else
            d.reset(new MapData);
    }

    bool isSharedWith(const QMap<Key, T> & other) const noexcept
    {
        return d == other.d; // also this makes little sense?
    }

    //Returns true if the map contains an item with key key;
    //otherwise returns false.
    bool contains(const Key & key) const
    {
        if (!d)      return false;

        auto   i  = d->m.find(key);
        return i != d->m.end();
    }

    //Returns the value associated with the key key.
    //If the map contains no item with key key,
    //the function returns defaultValue.  If no defaultValue is specified,
    //the function returns a default-constructed value.
    T value(const Key & key, const T & defaultValue = T()) const
    {
        if (!d)  return defaultValue;

        const auto i = d->m.find(key);

        if (i != d->m.cend())  return i->second;

        return defaultValue;
    }

    //template <typename T>
    //class QList { } ;
    QList<T> values() const
    {
        if (!d)  return {};

        return d->values();
    }
    //Returns a list containing all the values in the map,
    //in ascending order of their keys. If a key is associated with multiple
    //values, all of its values will be in the list, and not just the
    //most recently inserted one. This function creates a new list,
    //in linear time. The time and memory use that entails详细说明 can be
    //avoided by iterating from keyValueBegin() to keyValueEnd().

    T & operator[](const Key & key) //返回值
    {
        detach();
        auto i = d->m.find(key);
        if (i == d->m.end())
            i = d->m.insert({key, T()}).first;
        return i->second;
    }

    // CHANGE: return T, not const T!
    T operator[](const Key & key) const //返回引用,但对 this 的修饰符变化了
    {
        return value(key);
    }

    //返回具有值 value 的第一个键,如果 map 中没有具有值 value 的项,则返回 defaultKey。
    //如果没有提供 defaultKey,则函数返回一个默认构造的键。
    //这个函数可能会很慢(线性时间),
    //因为 QMap 的内部数据结构是为快速按键而不是按值进行查找而优化的。
    Key key(const T & value, const Key & defaultKey = Key()) const
    {
        if (!d)
            return defaultKey;

        return d->key(value, defaultKey);
    }

    //Returns a list containing all the keys in the map in ascending order.
    //The order is guaranteed to be the same as that used by values().
    //This function creates a new list, in linear time. The time and
    //memory use that entails can be avoided by
    //  iterating from keyBegin() to keyEnd().
    QList<Key> keys() const
    {
        if (!d)  return {};

        return d->keys();
    }

    QList<Key> keys(const T & value) const
    {
        if (!d)   return {};

        return d->keys(value);
    }

    //Returns a reference to the smallest key in the map.
    //This function assumes that the map is not empty.
    inline const Key & firstKey() const  //返回的都是左值引用
    { Q_ASSERT(!isEmpty()); return constBegin().key(); }

    inline        T  & first   () { Q_ASSERT(!isEmpty()); return *begin(); }

    inline const  T  & first   () const  //返回的都是左值引用
    { Q_ASSERT(!isEmpty()); return * constBegin(); }
    //Returns a reference to the first value in the map,
    //that is the value mapped to the smallest key.
    //This function assumes that the map is not empty.
    //When unshared (or const version is called),
    //this executes in constant time.

    inline const Key &  lastKey() const
    { Q_ASSERT(!isEmpty()); return (--constEnd()).key(); }

    inline const  T  &  last   () const
    { Q_ASSERT(!isEmpty()); return *(--constEnd()); }

    inline        T  &  last   () { Q_ASSERT(!isEmpty()); return *(--end()); }

    //Removes all the items that have the key key from the map.
    //Returns the number of items removed which will be 1 if the
    //key exists in the map, and 0 otherwise.
    size_type remove(const Key & key) //删除
    {
        if (!d)
            return 0;

        if (!d.isShared())
            return size_type(d->m.erase(key));

        MapData * newData = new MapData;
        size_type result = newData->copyIfNotEquivalentTo(d->m, key);

        d.reset(newData);

        return result;
    }

    template <typename Predicate>
    size_type removeIf(Predicate pred) //带断言的删除
    {
        return QtPrivate::associative_erase_if(*this, pred);
    }

    //从映射中删除具有键 key 的项,并返回与之关联的值。
    //如果该条目不在映射中,该函数将简单地返回一个默认构造的值。
    //如果映射中键的条目有多个则只会删除并返回最近插入的条目。
    //如果您不使用返回值,则remove()更高效。
    T take(const Key & key)
    {
        if (!d)
            return T();

        // TODO: improve. There is no need of copying all the
        // elements (the one to be removed can be skipped).
        detach();

        auto i = d->m.find(key);
        if (i != d->m.end()) {
            T result(std::move(i->second));
            d->m.erase(i);
            return result;
        }
        return T();
    }

    void clear() //Removes all items from the map.
    {
        if (!d)              return;

        if (!d.isShared())   d->m.clear();
        else                 d.reset();
    }


    class const_iterator; //定义就在下面。以下这些内容是为了与 STL库的函数接口形式同步

    class iterator
    {
        friend class QMap<Key, T>  ; //声明友元类
        friend class const_iterator;

        typename Map::iterator    i; //定义本类的数据成员,简化了变量名

        explicit iterator(typename Map::iterator it) : i(it) {} //有参构造函数

    public:
        using iterator_category = std::bidirectional_iterator_tag; //双向迭代遍历
        using   difference_type = qptrdiff;
        using        value_type = T       ;
        using           pointer = T *     ;
        using         reference = T &     ;

        iterator() = default; //默认构造函数

        const Key & key  () const { return i->first ; } //<key  , value > 键值对
               T  & value() const { return i->second; } //<first, second>

        T & operator *() const { return  i->second; } //迭代器 iterator指向的都是值 value
        T * operator->() const { return &i->second; }

        friend bool operator==(const iterator & lhs, const iterator & rhs)
        { return lhs.i == rhs.i; }

        friend bool operator!=(const iterator & lhs, const iterator & rhs)
        { return lhs.i != rhs.i; }

        iterator & operator++(   ) //++a
        {
            ++i;
            return * this;
        }

        iterator   operator++(int) //a++
        {
            iterator r = *this;
            ++i;
            return r;
        }

        iterator & operator--(   ) //--a
        {
            --i;
            return *this;
        }

        iterator   operator--(int) //a--
        {
            iterator r = *this;
            --i;
            return r;
        }
    }; //完结 class iterator

    class const_iterator
    {
        friend  class  QMap<Key, T>   ; //定义友元类

        typename Map::const_iterator i; //定义本类的数据成员

        explicit const_iterator(typename Map::const_iterator it) : i(it) {} //有参构造函数

    public:
        using iterator_category = std::bidirectional_iterator_tag; //双向迭代遍历
        using   difference_type = qptrdiff;
        using        value_type = T;
        using           pointer = const T *;
        using         reference = const T &;

        const_iterator() = default; //默认构造函数

        Q_IMPLICIT const_iterator(const iterator & o) : i(o.i) {} //copy 构造函数

        const Key & key  () const { return i->first ; }
        const  T  & value() const { return i->second; }

        const  T  & operator *() const { return  i->second; }
        const  T  * operator->() const { return &i->second; }

        friend bool operator==(const const_iterator & lhs, const const_iterator & rhs)
        { return lhs.i == rhs.i; }

        friend bool operator!=(const const_iterator & lhs, const const_iterator & rhs)
        { return lhs.i != rhs.i; }

        const_iterator &operator++()
        {
            ++i;
            return *this;
        }

        const_iterator operator++(int)
        {
            const_iterator r = *this;
            ++i;
            return r;
        }

        const_iterator &operator--()
        {
            --i;
            return *this;
        }

        const_iterator operator--(int)
        {
            const_iterator r = *this;
            --i;
            return r;
        }
    }; //完结 class const_iterator

    class key_iterator    //又定义了一个新的迭代器,名字不同于 STL库
    {
        const_iterator i; //本类的数据成员就是一个上面的常量迭代器

    public:
        typedef typename const_iterator::iterator_category iterator_category;
        typedef typename const_iterator::difference_type   difference_type;
        typedef       Key   value_type; //迭代器的值,就是键值对中的键
        typedef const Key * pointer   ;
        typedef const Key & reference ;

        key_iterator() = default; //默认构造函数

        explicit key_iterator(const_iterator o) : i(o) { } //有参构造函数

        const Key & operator *() const { return  i.key(); }
        const Key * operator->() const { return &i.key(); }

        bool operator==(key_iterator o) const { return i == o.i; }
        bool operator!=(key_iterator o) const { return i != o.i; }

        inline key_iterator & operator++(   ) { ++i;    return * this     ; }
        inline key_iterator   operator++(int) { return  key_iterator(i++) ; }

        inline key_iterator & operator--(   ) { --i;    return *this    ; }
        inline key_iterator   operator--(int) { return key_iterator(i--); }

        const_iterator base() const { return i; } //返回自己封装的数据成员,常量迭代器
    }; //完结 class key_iterator

    typedef QKeyValueIterator<const Key &, const T &, const_iterator>
            const_key_value_iterator;

    typedef QKeyValueIterator<const Key &,       T &, iterator>
            key_value_iterator;

    // STL style 还是遵循于 STL库的形式。减少记忆量,都是容器
          iterator      begin()
    { detach(); return iterator(d->m.begin()); }

    const_iterator      begin() const
    { if (!d) return const_iterator(); return const_iterator(d->m.cbegin()); }

    const_iterator constBegin() const { return begin(); }

    const_iterator     cbegin() const { return begin(); }

          iterator      end() { detach(); return iterator(d->m.end()); }

    const_iterator      end() const
    { if (!d) return const_iterator(); return const_iterator(d->m.end()); }

    const_iterator constEnd() const { return end(); }

    const_iterator     cend() const { return end(); }

    key_iterator keyBegin() const { return key_iterator(begin()); }
    key_iterator keyEnd  () const { return key_iterator(end()); }

          key_value_iterator      keyValueBegin()
    { return key_value_iterator(begin()); }

    const_key_value_iterator      keyValueBegin() const
    { return const_key_value_iterator(begin()); }

    const_key_value_iterator constKeyValueBegin() const
    { return const_key_value_iterator(begin()); }

          key_value_iterator      keyValueEnd  ()
    { return key_value_iterator(end()); }

    const_key_value_iterator      keyValueEnd() const
    { return const_key_value_iterator(end()); }

    const_key_value_iterator constKeyValueEnd() const
    { return const_key_value_iterator(end()); }

    iterator erase(const_iterator it)
    {
        return erase(it, std::next(it));
    }

    iterator erase(const_iterator afirst, const_iterator alast)
    {
        if (!d)
            return iterator();

        if (!d.isShared())
            return iterator(d->m.erase(afirst.i, alast.i));

        auto result = d->erase(afirst.i, alast.i);
        d.reset(result.data);
        return iterator(result.it);
    }

    // more Qt
    typedef       iterator      Iterator;
    typedef const_iterator ConstIterator;

          iterator      find(const Key & key) //本函数返回的是迭代器
    {
        detach();
        return iterator(d->m.find(key));
    }

    const_iterator      find(const Key & key) const
    {
        if (!d)
            return const_iterator();
        return const_iterator(d->m.find(key));
    }

    const_iterator constFind(const Key & key) const
    {
        return find(key);
    }

          iterator lowerBound(const Key & key)
    {
        detach();
        return iterator(d->m.lower_bound(key));
    }

    const_iterator lowerBound(const Key & key) const
    {
        if (!d)
            return const_iterator();
        return const_iterator(d->m.lower_bound(key));
    }
    //Returns an iterator pointing to the first item with key key in the map.
    //If the map contains no item with key key,
    //the function returns an iterator to the nearest item with a greater key.

    //Returns an iterator pointing to the item that immediately follows the
    //last item with key key in the map. If the map contains no item with key key,
    //the function returns an iterator to the nearest item with a greater key.
          iterator upperBound(const Key & key)
    {
        detach();
        return iterator(d->m.upper_bound(key));
    }

    const_iterator upperBound(const Key & key) const
    {
        if (!d)
            return const_iterator();
        return const_iterator(d->m.upper_bound(key));
    }

    //Inserts a new item with the key key and a value of value.
    //If there is already an item with the key key,
    //that item's value is replaced with value.
    iterator insert(                    const Key & key, const T & value)
    {
        // TODO: improve. In case of assignment, why copying first?
        detach();
        return iterator(d->m.insert_or_assign(key, value).first);
    }

    //插入一个新项,其键为 key,值为 value,提示位置为 pos,指示插入的位置。
    //如果constBegin()被用作提示,它表示该键小于映射中的任何键,
    //而constEnd()表示该键(严格大于映射中的任何键。
    //否则,提示应满足条件(pos-1)。key()<key<=pos.key()。
    //如果提示pos是错误的,则会被忽略并执行常规插入。
    //如果已经有一个键为 key的项,则将该项的值替换为 value。
    //如果提示正确且地图未共享,则插入操作在平均时间复杂度为常数的时间内执行。
    //当从已排序的数据创建地图时,使用constBegin()插入最大键比使用constEnd()按排序顺序插入更快,
    //  因为constEnd()-1(用于检查提示是否有效)需要对数时间。
    //注意:谨慎使用提示。从较旧的共享实例中提供迭代器可能会导致崩溃,
    //  但也有风险会悄无声息地破坏映射和 pos 映射。
    iterator insert(const_iterator pos, const Key & key, const T & value)
    {
        // TODO: improve. In case of assignment, why copying first?
        typename Map::const_iterator dpos;
        if (!d || d.isShared()) {
            auto posDistance = d ? std::distance(d->m.cbegin(), pos.i) : 0;
            detach();
            dpos = std::next(d->m.cbegin(), posDistance);
        } else {
            dpos = pos.i;
        }
        return iterator(d->m.insert_or_assign(dpos, key, value));
    }

    void insert(const QMap<Key, T> & map)
    {
        // TODO: improve. In case of assignment, why copying first?
        if (map.isEmpty())
            return;

        detach();

#ifdef __cpp_lib_node_extract  // if是成立的
        auto copy = map.d->m;
        copy.merge(std::move(d->m));
        d->m = std::move(copy);
#else
#endif
    }

    void insert(QMap<Key, T> && map)
    {
        if (!map.d || map.d->m.empty())
            return;

        if (map.d.isShared()) {
            // fall back to a regular copy
            insert(map);
            return;
        }

        detach();

#ifdef __cpp_lib_node_extract
        map.d->m.merge(std::move(d->m));
        *this = std::move(map);
#else
#endif
    }

    // STL compatibility
    inline bool empty() const
    {
        return isEmpty();
    }

    //返回一对迭代器,它们限定了存储在键下的值范围【first,second)
    QPair<iterator, iterator> equal_range(const Key & akey)
    {
        detach();
        auto result = d->m.equal_range(akey);
        return {iterator(result.first), iterator(result.second)};
    }

    QPair<const_iterator, const_iterator> equal_range(const Key & akey) const
    {
        if (!d)
            return {};
        auto result = d->m.equal_range(akey);
        return {const_iterator(result.first), const_iterator(result.second)};
    }
}; //完结 class QMap ++++++++++++++++++++++++++++++++++++

Q_DECLARE_ASSOCIATIVE_ITERATOR(Map)
Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Map)

template <typename Key, typename T, typename Predicate>
qsizetype erase_if(QMap<Key, T> & map, Predicate pred)
{
    return QtPrivate::associative_erase_if(map, pred);
}

// template <class Key, class T>
// class QMultiMap {....};  //l

QT_END_NAMESPACE

#endif // QMAP_H

(10)

谢谢

D:\Tool\Qt5.12.12\5.12.12\mingw73_64\include\QtCore\qtypeinfo.h:215: error: invalid application of 'sizeof' to incomplete type 'QMap<QString, QString>' In file included from D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qglobal.h:1204:0, from D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qnamespace.h:43, from D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qobjectdefs.h:48, from D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qobject.h:46, from D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/QObject:1, from GeneratedFiles\moc\../../paramejson.h:4, from GeneratedFiles\moc\moc_paramejson.cpp:9: D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qtypeinfo.h: In instantiation of 'class QTypeInfo<QMap<QString, QString> >': D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qlist.h:496:31: required from 'void QList<T>::node_destruct(QList<T>::Node*, QList<T>::Node*) [with T = QMap<QString, QString>]' D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qlist.h:868:18: required from 'void QList<T>::dealloc(QListData::Data*) [with T = QMap<QString, QString>]' D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qlist.h:830:16: required from 'QList<T>::~QList() [with T = QMap<QString, QString>]' GeneratedFiles\moc\../../paramejson.h:9:8: required from 'void QList<T>::node_destruct(QList<T>::Node*, QList<T>::Node*) [with T = NodeData]' D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qlist.h:868:18: required from 'void QList<T>::dealloc(QListData::Data*) [with T = NodeData]' D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qlist.h:830:16: required from 'QList<T>::~QList() [with T = NodeData]' GeneratedFiles\moc\../../paramejson.h:16:7: required from here D:/Tool/Qt5.12.12/5.12.12/mingw73_64/include/QtCore/qtypeinfo.h:215:26: error: invalid application of 'sizeof' to incomplete type 'QMap<QString, QString>' isLarge = (sizeof
09-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangzhangkeji

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值