Generated reference › API — ICoreEssentials/Containers
kind: generated#api#icoreessentials-containers

API — ICoreEssentials/Containers

The public contract of 6 header(s) under src/ICoreEssentials/Containers — 6 class/struct definition(s), 64 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.

ICoreArray.h#

src/ICoreEssentials/Containers/ICoreArray.h

ICoreArray#

ICoreArray.h:11 · class · 9 declaration(s)

class ICoreArray {
public:
    ICoreArray(const size_t r = 0, const size_t c = 0) : rows(r), cols(c), data(r * c) {}

    std::vector<T> getAllEntriesAsList() const {
        return  data;
    }

    // Resize explicitly
    void resize(const size_t r, const size_t c) {
        grow(r, c);
    }

    // Safe setter/getter with auto-grow
    T& operator()(const size_t i, size_t j) {
        if (i >= rows || j >= cols) {
            grow(std::max(rows, i + 1), std::max(cols, j + 1));
        }
        return data[i * cols + j];
    }

    const T& operator()(size_t i, size_t j) const {
        return data[i * cols + j]; // assume valid for const
    }

    ICoreArray<T> slice(const size_t r1, const size_t r2, const size_t c1, const size_t c2) const {
        ICoreArray<T> result(r2 - r1 + 1, c2 - c1 + 1);

        for (size_t i = r1; i <= r2; ++i)
            for (size_t j = c1; j <= c2; ++j)
                result(i - r1, j - c1) = (*this)(i, j);

        return result;
    }

    // Full row
    ICoreArray<T> row(const size_t r) const {
        return slice(r, r, 0, cols - 1);
    }

    // Full column
    ICoreArray<T> col(const size_t c) const {
        return slice(0, rows - 1, c, c);
    }

    ICoreArray<T> operator|(const ICoreArray<T>& other) const {
        size_t newRows = std::max(rows, other.rows);
        size_t newCols = cols + other.cols;

        ICoreArray<T> result(newRows, newCols);

        // copy left
        for (size_t i = 0; i < rows; ++i)
            for (size_t j = 0; j < cols; ++j)
                result(i,j) = (*this)(i,j);

        // copy right
        for (size_t i = 0; i < other.rows; ++i)
            for (size_t j = 0; j < other.cols; ++j)
                result(i, j + cols) = other(i,j);

        return result;
    }

    ICoreArray<T> operator&(const ICoreArray<T>& other) const {
        size_t newRows = rows + other.rows;
        size_t newCols = std::max(cols, other.cols);

        ICoreArray<T> result(newRows, newCols);

        // copy top
        for (size_t i = 0; i < rows; ++i)
            for (size_t j = 0; j < cols; ++j)
                result(i,j) = (*this)(i,j);

        // copy bottom
        for (size_t i = 0; i < other.rows; ++i)
            for (size_t j = 0; j < other.cols; ++j)
                result(i + rows, j) = other(i,j);

        return result;
    }

    size_t getRows() const { return rows; }
    size_t getCols() const { return cols; }
};
};

ICoreHashMap.h#

src/ICoreEssentials/Containers/ICoreHashMap.h

ICoreHashMap -- the project's own unordered key/value map.

PHASE 1 (current): a thin value wrapper around QHash<K, V>. Every operation forwards. Phase 3 replaces the member with std::unordered_map<K, V>.

The conversion shape, the class-not-alias decision and the "Qt's operators are templates, so deduction ignores our conversions" argument are all derived at the top of ICoreList.h -- read that file first; this one only records what is different.

⚠ THIS WRAPPER FRONTS QHash ONLY. QMap IS NOT PART OF IT.

The README's wave-8 line and the plan's B24 row both said "ICoreHashMap -- wraps QHash, QMap", and B24 found that to be wrong in a way that would not

ICoreHashMap#

ICoreHashMap.h:52 · class · 6 declaration(s)

class ICoreHashMap {
public:
    using key_type       = K;
    using mapped_type    = V;
    using iterator       = typename QHash<K, V>::iterator;
    using const_iterator = typename QHash<K, V>::const_iterator;
    using size_type      = qsizetype;

    // --- construction ------------------------------------------------------
    ICoreHashMap() = default;
    ICoreHashMap(const ICoreHashMap&) = default;
    ICoreHashMap(ICoreHashMap&&) noexcept = default;
    ICoreHashMap& operator=(const ICoreHashMap&) = default;
    ICoreHashMap& operator=(ICoreHashMap&&) noexcept = default;
    ~ICoreHashMap() = default;

    ICoreHashMap(const QHash<K, V>& h) : m_h(h) {}
    ICoreHashMap(QHash<K, V>&& h) noexcept : m_h(std::move(h)) {}
    ICoreHashMap(std::initializer_list<std::pair<K, V>> items) : m_h(items) {}
    template <class It, class = typename std::iterator_traits<It>::iterator_category>
    ICoreHashMap(It first_, It last_) : m_h(first_, last_) {}

    // --- interop with the Qt backing store ---------------------------------
    operator const QHash<K, V>&() const noexcept { return m_h; }
    const QHash<K, V>& toQHash() const noexcept { return m_h; }

    // --- size and state ----------------------------------------------------
    bool isEmpty() const noexcept { return m_h.isEmpty(); }
    bool empty() const noexcept { return m_h.isEmpty(); }
    qsizetype size() const noexcept { return m_h.size(); }
    qsizetype count() const noexcept { return m_h.size(); }
    void clear() { m_h.clear(); }
    void reserve(qsizetype n) { m_h.reserve(n); }
    void squeeze() { m_h.squeeze(); }
    void detach() { m_h.detach(); }

    // --- lookup ------------------------------------------------------------
    bool contains(const K& key) const { return m_h.contains(key); }
    V value(const K& key) const { return m_h.value(key); }
    V value(const K& key, const V& fallback) const { return m_h.value(key, fallback); }
    V& operator[](const K& key) { return m_h[key]; }
    V operator[](const K& key) const { return m_h[key]; }
    K key(const V& value) const { return m_h.key(value); }
    K key(const V& value, const K& fallback) const { return m_h.key(value, fallback); }
    qsizetype count(const K& key) const { return m_h.count(key); }

    iterator find(const K& key) { return m_h.find(key); }
    const_iterator find(const K& key) const { return m_h.find(key); }
    const_iterator constFind(const K& key) const { return m_h.constFind(key); }

    // keys() and values() hand back the WRAPPER, not QList -- otherwise every
    // `hash.keys()` would put a Qt type back into a migrated file, which is
    // exactly what the rename is for. This is why the umbrella must include
    // ICoreList.h before this header.
    ICoreList<K> keys() const { return ICoreList<K>(m_h.keys()); }
    ICoreList<K> keys(const V& value) const { return ICoreList<K>(m_h.keys(value)); }
    ICoreList<V> values() const { return ICoreList<V>(m_h.values()); }

    // --- modification ------------------------------------------------------
    iterator insert(const K& key, const V& value) { return m_h.insert(key, value); }
    void insert(const ICoreHashMap& other) { m_h.insert(other.m_h); }
    void insert(const QHash<K, V>& other) { m_h.insert(other); }
    template <class... Args>
    iterator emplace(const K& key, Args&&... args) { return m_h.emplace(key, std::forward<Args>(args)...); }
    qsizetype remove(const K& key) { return m_h.remove(key); }
    template <class Predicate>
    qsizetype removeIf(Predicate pred) { return m_h.removeIf(pred); }
    V take(const K& key) { return m_h.take(key); }
    iterator erase(const_iterator pos) { return m_h.erase(pos); }
    void swap(ICoreHashMap& other) noexcept { m_h.swap(other.m_h); }

    // --- iteration ---------------------------------------------------------
    iterator begin() { return m_h.begin(); }
    iterator end() { return m_h.end(); }
    const_iterator begin() const { return m_h.begin(); }
    const_iterator end() const { return m_h.end(); }
    const_iterator cbegin() const { return m_h.cbegin(); }
    const_iterator cend() const { return m_h.cend(); }
    const_iterator constBegin() const { return m_h.constBegin(); }
    const_iterator constEnd() const { return m_h.constEnd(); }
    auto keyBegin() const { return m_h.keyBegin(); }
    auto keyEnd() const { return m_h.keyEnd(); }
    auto keyValueBegin() { return m_h.keyValueBegin(); }
    auto keyValueEnd() { return m_h.keyValueEnd(); }
    auto keyValueBegin() const { return m_h.keyValueBegin(); }
    auto keyValueEnd() const { return m_h.keyValueEnd(); }
    auto asKeyValueRange() { return m_h.asKeyValueRange(); }
    auto asKeyValueRange() const { return m_h.asKeyValueRange(); }

};

ICoreList.h#

src/ICoreEssentials/Containers/ICoreList.h

ICoreList -- the project's own sequence container.

PHASE 1 (current): a thin value wrapper around QList<T>. Every operation forwards. Phase 3 replaces the member with std::vector<T>; there is nothing in the API below that std::vector cannot carry, which is the point of keeping the surface small.

DESIGN NOTES -- read before changing anything, none of these was free.

  • IT IS A CLASS TEMPLATE, NOT AN ALIAS -- and the placeholder this file

replaced said the opposite ("probably an alias rather than a class, QList is already std::vector-shaped in Qt 6"). That suggestion was measured and rejected, because template <class T> using ICoreList = QList<T> is not a wrapper at all: it is the SAME type under a second

ICoreList#

ICoreList.h:73 · class · 6 declaration(s)

class ICoreList {
public:
    using value_type      = T;
    using iterator        = typename QList<T>::iterator;
    using const_iterator  = typename QList<T>::const_iterator;
    using reference       = T&;
    using const_reference = const T&;
    using size_type       = qsizetype;

    // --- construction ------------------------------------------------------
    ICoreList() = default;
    ICoreList(const ICoreList&) = default;
    ICoreList(ICoreList&&) noexcept = default;
    ICoreList& operator=(const ICoreList&) = default;
    ICoreList& operator=(ICoreList&&) noexcept = default;
    ~ICoreList() = default;

    // Implicit on purpose: lists arrive from Qt-declared API constantly
    // (QHash::keys(), QWidget::actions(), QTreeWidget::selectedItems()), and
    // an explicit constructor would turn every one of those into a cast.
    ICoreList(const QList<T>& l) : m_l(l) {}
    ICoreList(QList<T>&& l) noexcept : m_l(std::move(l)) {}
    ICoreList(std::initializer_list<T> items) : m_l(items) {}
    explicit ICoreList(qsizetype n) : m_l(n) {}
    ICoreList(qsizetype n, const T& value) : m_l(n, value) {}
    // CONSTRAINED, and it has to be -- see the H12 note at the foot of this
    // file. An unconstrained `template <class It> ICoreList(It, It)` makes the
    // wrapper constructible from ANY two arguments, which turns every
    // `list.append({a, b})` into an ambiguity that the plain Qt type does not
    // have. The iterator_category requirement removes it from consideration
    // for anything that is not actually an iterator.
    template <class It, class = typename std::iterator_traits<It>::iterator_category>
    ICoreList(It first_, It last_) : m_l(first_, last_) {}

    // --- interop with the Qt backing store ---------------------------------
    operator const QList<T>&() const noexcept { return m_l; }
    const QList<T>& toQList() const noexcept { return m_l; }

    // --- size and state ----------------------------------------------------
    bool isEmpty() const noexcept { return m_l.isEmpty(); }
    bool empty() const noexcept { return m_l.isEmpty(); }
    qsizetype size() const noexcept { return m_l.size(); }
    qsizetype count() const noexcept { return m_l.size(); }
    qsizetype length() const noexcept { return m_l.length(); }
    void clear() { m_l.clear(); }
    void reserve(qsizetype n) { m_l.reserve(n); }
    void resize(qsizetype n) { m_l.resize(n); }
    void resize(qsizetype n, const T& value) { m_l.resize(n, value); }
    void squeeze() { m_l.squeeze(); }
    void detach() { m_l.detach(); }

    // --- element access ----------------------------------------------------
    const T& at(qsizetype i) const { return m_l.at(i); }
    T& operator[](qsizetype i) { return m_l[i]; }
    const T& operator[](qsizetype i) const { return m_l[i]; }
    T& first() { return m_l.first(); }
    const T& first() const { return m_l.first(); }
    T& last() { return m_l.last(); }
    const T& last() const { return m_l.last(); }
    const T& constFirst() const { return m_l.constFirst(); }
    const T& constLast() const { return m_l.constLast(); }
    T& front() { return m_l.front(); }
    const T& front() const { return m_l.front(); }
    T& back() { return m_l.back(); }
    const T& back() const { return m_l.back(); }
    T value(qsizetype i) const { return m_l.value(i); }
    T value(qsizetype i, const T& fallback) const { return m_l.value(i, fallback); }
    T* data() { return m_l.data(); }
    const T* data() const { return m_l.data(); }
    const T* constData() const { return m_l.constData(); }

    // --- iteration ---------------------------------------------------------
    iterator begin() { return m_l.begin(); }
    iterator end() { return m_l.end(); }
    const_iterator begin() const { return m_l.begin(); }
    const_iterator end() const { return m_l.end(); }
    const_iterator cbegin() const { return m_l.cbegin(); }
    const_iterator cend() const { return m_l.cend(); }
    const_iterator constBegin() const { return m_l.constBegin(); }
    const_iterator constEnd() const { return m_l.constEnd(); }
    auto rbegin() { return m_l.rbegin(); }
    auto rend() { return m_l.rend(); }
    auto rbegin() const { return m_l.rbegin(); }
    auto rend() const { return m_l.rend(); }

    // --- adding and removing -----------------------------------------------
    void append(const T& v) { m_l.append(v); }
    void append(T&& v) { m_l.append(std::move(v)); }
    void append(const ICoreList& other) { m_l.append(other.m_l); }
    void append(const QList<T>& other) { m_l.append(other); }
    void prepend(const T& v) { m_l.prepend(v); }
    void prepend(T&& v) { m_l.prepend(std::move(v)); }
    void push_back(const T& v) { m_l.push_back(v); }
    void push_back(T&& v) { m_l.push_back(std::move(v)); }
    void push_front(const T& v) { m_l.push_front(v); }
    void pop_back() { m_l.pop_back(); }
    void pop_front() { m_l.pop_front(); }
    template <class... Args>
    T& emplaceBack(Args&&... args) { return m_l.emplaceBack(std::forward<Args>(args)...); }
    template <class... Args>
    T& emplace_back(Args&&... args) { return m_l.emplace_back(std::forward<Args>(args)...); }
    void insert(qsizetype i, const T& v) { m_l.insert(i, v); }
    iterator insert(const_iterator before, const T& v) { return m_l.insert(before, v); }
    void removeAt(qsizetype i) { m_l.removeAt(i); }
    qsizetype removeAll(const T& v) { return m_l.removeAll(v); }
    bool removeOne(const T& v) { return m_l.removeOne(v); }
    void removeFirst() { m_l.removeFirst(); }
    void removeLast() { m_l.removeLast(); }
    template <class Predicate>
    qsizetype removeIf(Predicate pred) { return m_l.removeIf(pred); }
    T takeAt(qsizetype i) { return m_l.takeAt(i); }
    T takeFirst() { return m_l.takeFirst(); }
    T takeLast() { return m_l.takeLast(); }
    iterator erase(const_iterator pos) { return m_l.erase(pos); }
    iterator erase(const_iterator first_, const_iterator last_) { return m_l.erase(first_, last_); }
    void swapItemsAt(qsizetype i, qsizetype j) { m_l.swapItemsAt(i, j); }
    void move(qsizetype from, qsizetype to) { m_l.move(from, to); }
    void fill(const T& v) { m_l.fill(v); }

    // --- searching ---------------------------------------------------------
    bool contains(const T& v) const { return m_l.contains(v); }
    qsizetype indexOf(const T& v, qsizetype from = 0) const { return m_l.indexOf(v, from); }
    qsizetype lastIndexOf(const T& v, qsizetype from = -1) const { return m_l.lastIndexOf(v, from); }
    qsizetype count(const T& v) const { return m_l.count(v); }
    bool startsWith(const T& v) const { return m_l.startsWith(v); }
    bool endsWith(const T& v) const { return m_l.endsWith(v); }

    // --- slicing (returns the wrapper, so a chain never leaks Qt) ----------
    ICoreList mid(qsizetype pos, qsizetype n = -1) const { return ICoreList(m_l.mid(pos, n)); }
    ICoreList sliced(qsizetype pos) const { return ICoreList(m_l.sliced(pos)); }
    ICoreList sliced(qsizetype pos, qsizetype n) const { return ICoreList(m_l.sliced(pos, n)); }
    ICoreList first(qsizetype n) const { return ICoreList(m_l.first(n)); }
    ICoreList last(qsizetype n) const { return ICoreList(m_l.last(n)); }

    // --- compound operators (members, so they join no Qt overload set) ------
    ICoreList& operator<<(const T& v) { m_l << v; return *this; }
    ICoreList& operator<<(const ICoreList& other) { m_l << other.m_l; return *this; }
    ICoreList& operator<<(const QList<T>& other) { m_l << other; return *this; }
    ICoreList& operator+=(const T& v) { m_l += v; return *this; }
    ICoreList& operator+=(const ICoreList& other) { m_l += other.m_l; return *this; }
    ICoreList& operator+=(const QList<T>& other) { m_l += other; return *this; }
    ICoreList operator+(const ICoreList& other) const { return ICoreList(m_l + other.m_l); }

    void swap(ICoreList& other) noexcept { m_l.swap(other.m_l); }

};

ICoreSet.h#

src/ICoreEssentials/Containers/ICoreSet.h

ICoreSet -- the project's own unordered unique-element container.

PHASE 1 (current): a thin value wrapper around QSet<T>. Every operation forwards. Phase 3 replaces the member with std::unordered_set<T>.

The conversion shape and the class-not-alias decision are derived at the top of ICoreList.h; this header only records what is different.

WHAT THIS TYPE IS ACTUALLY FOR, measured rather than assumed: 38 of the project's 40 QSet occurrences are QSet<ICoreString>, and every one of them is a seen-set -- handles already emitted, names already taken, warnings already issued. The API below is sized for that: insert, contains, iterate, and the initialiser-list form the SimulinkBridge keyword tables use. Set ALGEBRA (unite/intersect/subtract) is forwarded because QSet has it, but no

ICoreSet#

ICoreSet.h:34 · class · 6 declaration(s)

class ICoreSet {
public:
    using value_type     = T;
    using iterator       = typename QSet<T>::iterator;
    using const_iterator = typename QSet<T>::const_iterator;
    using size_type      = qsizetype;

    // --- construction ------------------------------------------------------
    ICoreSet() = default;
    ICoreSet(const ICoreSet&) = default;
    ICoreSet(ICoreSet&&) noexcept = default;
    ICoreSet& operator=(const ICoreSet&) = default;
    ICoreSet& operator=(ICoreSet&&) noexcept = default;
    ~ICoreSet() = default;

    ICoreSet(const QSet<T>& s) : m_s(s) {}
    ICoreSet(QSet<T>&& s) noexcept : m_s(std::move(s)) {}
    ICoreSet(std::initializer_list<T> items) : m_s(items) {}
    // Iterator-pair: ICoreRunDiagnosisPanel builds one straight out of a
    // QTreeWidget selection this way.
    template <class It, class = typename std::iterator_traits<It>::iterator_category>
    ICoreSet(It first_, It last_) : m_s(first_, last_) {}

    // --- interop with the Qt backing store ---------------------------------
    operator const QSet<T>&() const noexcept { return m_s; }
    const QSet<T>& toQSet() const noexcept { return m_s; }

    // --- size and state ----------------------------------------------------
    bool isEmpty() const noexcept { return m_s.isEmpty(); }
    bool empty() const noexcept { return m_s.isEmpty(); }
    qsizetype size() const noexcept { return m_s.size(); }
    qsizetype count() const noexcept { return m_s.size(); }
    void clear() { m_s.clear(); }
    void reserve(qsizetype n) { m_s.reserve(n); }
    void squeeze() { m_s.squeeze(); }
    void detach() { m_s.detach(); }

    // --- lookup ------------------------------------------------------------
    bool contains(const T& v) const { return m_s.contains(v); }
    bool contains(const ICoreSet& other) const { return m_s.contains(other.m_s); }
    iterator find(const T& v) { return m_s.find(v); }
    const_iterator find(const T& v) const { return m_s.find(v); }
    const_iterator constFind(const T& v) const { return m_s.constFind(v); }

    // Hands back the wrapper, not QList -- same reason as ICoreHashMap::keys().
    ICoreList<T> values() const { return ICoreList<T>(m_s.values()); }

    // --- modification ------------------------------------------------------
    iterator insert(const T& v) { return m_s.insert(v); }
    bool remove(const T& v) { return m_s.remove(v); }
    template <class Predicate>
    qsizetype removeIf(Predicate pred) { return m_s.removeIf(pred); }
    iterator erase(const_iterator pos) { return m_s.erase(pos); }
    void swap(ICoreSet& other) noexcept { m_s.swap(other.m_s); }

    // --- set algebra (forwarded, currently unused -- see the header note) ---
    ICoreSet& unite(const ICoreSet& other) { m_s.unite(other.m_s); return *this; }
    ICoreSet& intersect(const ICoreSet& other) { m_s.intersect(other.m_s); return *this; }
    ICoreSet& subtract(const ICoreSet& other) { m_s.subtract(other.m_s); return *this; }
    bool intersects(const ICoreSet& other) const { return m_s.intersects(other.m_s); }

    // --- iteration ---------------------------------------------------------
    iterator begin() { return m_s.begin(); }
    iterator end() { return m_s.end(); }
    const_iterator begin() const { return m_s.begin(); }
    const_iterator end() const { return m_s.end(); }
    const_iterator cbegin() const { return m_s.cbegin(); }
    const_iterator cend() const { return m_s.cend(); }
    const_iterator constBegin() const { return m_s.constBegin(); }
    const_iterator constEnd() const { return m_s.constEnd(); }

    // --- compound operators (members, so they join no Qt overload set) ------
    ICoreSet& operator<<(const T& v) { m_s << v; return *this; }
    ICoreSet& operator+=(const ICoreSet& other) { m_s += other.m_s; return *this; }
    ICoreSet& operator-=(const ICoreSet& other) { m_s -= other.m_s; return *this; }
    ICoreSet& operator|=(const ICoreSet& other) { m_s |= other.m_s; return *this; }
    ICoreSet& operator&=(const ICoreSet& other) { m_s &= other.m_s; return *this; }

};

ICoreSortedMap.h#

src/ICoreEssentials/Containers/ICoreSortedMap.h

ICoreSortedMap -- the project's own ORDERED key/value map.

PHASE 1 (current): a thin value wrapper around QMap<K, V>. Phase 3 replaces the member with std::map<K, V>, which has the same ordering guarantee.

WHY THIS TYPE EXISTS AT ALL -- it is not in the plan, and B24 added it.

The plan's B24 row and the README's wave-8 line both scheduled QMap to go behind ICoreHashMap alongside QHash. That is a silent behaviour change: QMap iterates in ascending key order, QHash's order is unspecified and salt-randomised per process. Phase 1 changes no behaviour, so they cannot share a wrapper.

And it would have mattered. QMap has exactly ONE call site --

ICoreSortedMap#

ICoreSortedMap.h:50 · class · 6 declaration(s)

class ICoreSortedMap {
public:
    using key_type       = K;
    using mapped_type    = V;
    using iterator       = typename QMap<K, V>::iterator;
    using const_iterator = typename QMap<K, V>::const_iterator;
    using size_type      = qsizetype;

    // --- construction ------------------------------------------------------
    ICoreSortedMap() = default;
    ICoreSortedMap(const ICoreSortedMap&) = default;
    ICoreSortedMap(ICoreSortedMap&&) noexcept = default;
    ICoreSortedMap& operator=(const ICoreSortedMap&) = default;
    ICoreSortedMap& operator=(ICoreSortedMap&&) noexcept = default;
    ~ICoreSortedMap() = default;

    ICoreSortedMap(const QMap<K, V>& m) : m_m(m) {}
    ICoreSortedMap(QMap<K, V>&& m) noexcept : m_m(std::move(m)) {}
    ICoreSortedMap(std::initializer_list<std::pair<K, V>> items) : m_m(items) {}

    // --- interop with the Qt backing store ---------------------------------
    operator const QMap<K, V>&() const noexcept { return m_m; }
    const QMap<K, V>& toQMap() const noexcept { return m_m; }

    // --- size and state ----------------------------------------------------
    bool isEmpty() const noexcept { return m_m.isEmpty(); }
    bool empty() const noexcept { return m_m.isEmpty(); }
    qsizetype size() const noexcept { return m_m.size(); }
    qsizetype count() const noexcept { return m_m.size(); }
    void clear() { m_m.clear(); }
    void detach() { m_m.detach(); }

    // --- lookup ------------------------------------------------------------
    bool contains(const K& key) const { return m_m.contains(key); }
    V value(const K& key) const { return m_m.value(key); }
    V value(const K& key, const V& fallback) const { return m_m.value(key, fallback); }
    V& operator[](const K& key) { return m_m[key]; }
    V operator[](const K& key) const { return m_m[key]; }
    K key(const V& value) const { return m_m.key(value); }
    K key(const V& value, const K& fallback) const { return m_m.key(value, fallback); }

    iterator find(const K& key) { return m_m.find(key); }
    const_iterator find(const K& key) const { return m_m.find(key); }
    const_iterator constFind(const K& key) const { return m_m.constFind(key); }

    // Hands back the wrapper, not QList -- same reason as ICoreHashMap::keys().
    // Unlike QHash's, these two come back in ascending key order, which is the
    // whole reason this type is separate.
    ICoreList<K> keys() const { return ICoreList<K>(m_m.keys()); }
    ICoreList<V> values() const { return ICoreList<V>(m_m.values()); }
    K firstKey() const { return m_m.firstKey(); }
    K lastKey() const { return m_m.lastKey(); }

    // --- modification ------------------------------------------------------
    iterator insert(const K& key, const V& value) { return m_m.insert(key, value); }
    void insert(const ICoreSortedMap& other) { m_m.insert(other.m_m); }
    qsizetype remove(const K& key) { return m_m.remove(key); }
    template <class Predicate>
    qsizetype removeIf(Predicate pred) { return m_m.removeIf(pred); }
    V take(const K& key) { return m_m.take(key); }
    iterator erase(const_iterator pos) { return m_m.erase(pos); }
    void swap(ICoreSortedMap& other) noexcept { m_m.swap(other.m_m); }

    // --- iteration (ascending by key -- the invariant this type exists for) -
    iterator begin() { return m_m.begin(); }
    iterator end() { return m_m.end(); }
    const_iterator begin() const { return m_m.begin(); }
    const_iterator end() const { return m_m.end(); }
    const_iterator cbegin() const { return m_m.cbegin(); }
    const_iterator cend() const { return m_m.cend(); }
    const_iterator constBegin() const { return m_m.constBegin(); }
    const_iterator constEnd() const { return m_m.constEnd(); }
    auto keyBegin() const { return m_m.keyBegin(); }
    auto keyEnd() const { return m_m.keyEnd(); }
    auto keyValueBegin() { return m_m.keyValueBegin(); }
    auto keyValueEnd() { return m_m.keyValueEnd(); }
    auto keyValueBegin() const { return m_m.keyValueBegin(); }
    auto keyValueEnd() const { return m_m.keyValueEnd(); }
    auto asKeyValueRange() { return m_m.asKeyValueRange(); }
    auto asKeyValueRange() const { return m_m.asKeyValueRange(); }

};

ICoreVariant.h#

src/ICoreEssentials/Containers/ICoreVariant.h

ICoreVariant#

ICoreVariant.h:63 · class · 31 declaration(s)

ICoreVariant -- a value of one of a handful of types, and the conversions between them.

class ICoreVariant {
public:
    // ⚠ THE STORAGE IS AN OPAQUE BUFFER (H1.7, 2026-08-14): the tag, the three
    // scalars and the ICoreString, held by value. A heap Impl would put a
    // malloc on every settings read -- ICoreSettings::value() returns one BY
    // VALUE and every `settings.value(k).toBool()` in ICoreUserPreferences
    // builds one -- so this takes the small-value residue like the rest of the
    // tier. Unlike ICorePoint and ICoreRect the state is NOT trivially
    // copyable, because it holds an ICoreString, so all six special members are
    // written out in the .cpp.
    //
    // The size is pinned by a static_assert against the real state, and the
    // .cpp's comment records what it measured. Do not adjust it by arithmetic.
    static constexpr std::size_t kNativeStorageSize  = 48;
    static constexpr std::size_t kNativeStorageAlign = 8;

    ICoreVariant();
    ICoreVariant(const ICoreVariant&);
    ICoreVariant(ICoreVariant&&) noexcept;
    ICoreVariant& operator=(const ICoreVariant&);
    ICoreVariant& operator=(ICoreVariant&&) noexcept;
    ~ICoreVariant();

    ICoreVariant(bool v);
    ICoreVariant(int v);
    ICoreVariant(unsigned v);
    ICoreVariant(long v);
    ICoreVariant(unsigned long v);
    ICoreVariant(long long v);
    ICoreVariant(unsigned long long v);
    ICoreVariant(double v);
    ICoreVariant(float v);
    ICoreVariant(const ICoreString& v);
    ICoreVariant(const char* v);

    // --- extraction ---------------------------------------------------------
    // The coercion table at the top of this file is the contract; the bodies
    // that implement it are in ICoreVariant.cpp and every rule is commented
    // there, beside the code rather than away from it.
    [[nodiscard]] bool toBool() const;
    [[nodiscard]] int toInt(bool* ok = nullptr) const;
    [[nodiscard]] unsigned toUInt(bool* ok = nullptr) const;
    [[nodiscard]] std::int64_t toLongLong(bool* ok = nullptr) const;
    [[nodiscard]] std::uint64_t toULongLong(bool* ok = nullptr) const;
    [[nodiscard]] double toDouble(bool* ok = nullptr) const;
    [[nodiscard]] float toFloat(bool* ok = nullptr) const;
    [[nodiscard]] ICoreString toString() const;

    [[nodiscard]] bool isValid() const noexcept;
    [[nodiscard]] bool isNull() const noexcept;

    void clear();
    void swap(ICoreVariant& other) noexcept;

    bool operator==(const ICoreVariant& other) const;
    bool operator!=(const ICoreVariant& other) const;

};