如何创建引用的自定义容器?

托里

免责声明:

我已经知道C ++委员会有理由不支持这一点,所以请不要回答告诉我“这是一个坏主意”,或者诸如此类的事情,我主要是想以此为乐,我个人发现了一种情况我想在哪里使用它。程序员总是会争论这种事情,所以请不要争论。

问题:

现在要说的是...我想使用QList,只是发现C ++不支持引用容器,所以我想也许我可以创建一个自定义引用容器,实际上将指针存储在引擎盖下(即无论如何,本质上是什么参考文献)。最好的方法是什么?(而且我不会接受“没有很好的办法”作为答案,让我们保持开放的态度吧!)

回答:

我设法实现了一个实现,并且我认为它工作得很好,我使用了QList,但是对于任何容器类型,其概念应该相同。我在这里为此创建了一个Github要点:ReferenceList.hpp或者,您可以在下面的答案中查看它。

即使我回答了自己的问题,也不要害怕就如何实现这一目标发表其他想法!

托里
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * ReferenceList.hpp                                                           *
 *                                                                             *
 * Copyright 2014 Tory Gaurnier <[email protected]>                  *
 *                                                                             *
 * This program is free software; you can redistribute it and/or modify        *
 * it under the terms of the GNU Lesser General Public License as published by *
 * the Free Software Foundation; version 3.                                    *
 *                                                                             *
 * This program is distributed in the hope that it will be useful,             *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of              *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
 * GNU Lesser General Public License for more details.                         *
 *                                                                             *
 * You should have received a copy of the GNU Lesser General Public License    *
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.       *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */


#ifndef REFERENCELIST_HPP
#define REFERENCELIST_HPP


#include <QDataStream>
#include <QDebug>
#include <QList>


/**
 * class ReferenceList
 *
 * Uses QList under the hood to store pointers, on the surface recieves and returns nothing but the
 * references.
 *
 * NOTE: Any method that calls it's QList<T*> counterpart with parameter T, T must not be const, if
 * it is then QList<T*> would have to be QList<const T *const> instead.
 */
template<class T>
class ReferenceList : public QList<T*> {
    public:
        // Forward declare iterators
        class const_iterator;
        class iterator;

        // Set iterators as friends
        friend class const_iterator;
        friend class iterator;


        ReferenceList() {}
        ReferenceList(const QList<T*> &other) : QList<T*>(other) {  }
        ReferenceList(const ReferenceList<T> &other) : QList<T*>(other) {  }
        ReferenceList(ReferenceList<T> &&other) : QList<T*>(std::move(other)) {  }
        ~ReferenceList() {}

        void append(T &value) {
            QList<T*>::append(&value);
        }

        void append(const ReferenceList<T> other) {
            QList<T*>::append(other);
        }

        const T & at(int i) const {
            return *QList<T*>::at(i);
        }

        T & back() {
            return *QList<T*>::back();
        }

        const T & back() const {
            return *QList<T*>::back();
        }

        iterator begin() {
            return iterator(iterator(QList<T*>::begin()));
        }

        const_iterator begin() const {
            return const_iterator(QList<T*>::begin());
        }

        const_iterator cbegin() const {
            return const_iterator(QList<T*>::cbegin());
        }

        const_iterator cend() const {
            return const_iterator(QList<T*>::cend());
        }

        void clear() {
            QList<T*>::clear();
        }

        const_iterator constBegin() const {
            return const_iterator(QList<T*>::constBegin());
        }

        const_iterator constEnd() const {
            return const_iterator(QList<T*>::constEnd());
        }

        bool contains(T &value) const {
            return QList<T*>::contains(&value);
        }

        int count(T &value) const {
            return QList<T*>::count(&value);
        }

        int count() const {
            return QList<T*>::count();
        }

        bool empty() const {
            return QList<T*>::empty();
        }

        iterator end() {
            return iterator(QList<T*>::end());
        }

        const_iterator end() const {
            return const_iterator(QList<T*>::end());
        }

        bool endsWith(T &value) const {
            return QList<T*>::endsWith(&value);
        }

        iterator erase(iterator pos) {
            return iterator(QList<T*>::erase(pos));
        }

        iterator erase(iterator begin, iterator end) {
            return iterator(QList<T*>::erase(begin, end));

        }

        T & first() {
            return *QList<T*>::first();
        }

        const T & first() const {
            return *QList<T*>::first();
        }

        /**
         * Inherited "from" methods are unsupported.
         */
        static ReferenceList<T> fromSet(const QSet<T> & set) = delete;
        static ReferenceList<T> fromStdList(const std::list<T> & list) = delete;
        static ReferenceList<T> fromVector(const QVector<T> & vector) = delete;

        T & front() {
            return *QList<T*>::front();
        }

        const T & front() const {
            return *QList<T*>::front();
        }

        int indexOf(T &value, int from = 0) const {
            return QList<T*>::indexOf(&value, from);
        }

        void insert(int i, T &value) {
            QList<T*>::insert(i, &value);
        }

        iterator insert(iterator before, T &value) {
            return iterator(QList<T*>::insert(before, &value));
        }

        bool isEmpty() const {
            return QList<T*>::isEmpty();
        }

        T & last() {
            return *QList<T*>::last();
        }

        const T & last() const {
            return *QList<T*>::last();
        }

        int lastIndexOf(T &value, int from = -1) const {
            return QList<T*>::lastIndexOf(&value, from);
        }

        int length() const {
            return QList<T*>::length();
        }

        ReferenceList<T> mid(int pos, int length = -1) const {
            return ReferenceList<T>(QList<T*>::mid(pos, length));
        }

        void move(int from, int to) {
            QList<T*>::move(from, to);
        }

        void pop_back() {
            QList<T*>::pop_back();
        }

        void pop_front() {
            QList<T*>::pop_front();
        }

        void prepend(T &value) {
            QList<T*>::prepend(&value);
        }

        void push_back(T &value) {
            QList<T*>::push_back(&value);
        }

        void push_front(T &value) {
            QList<T*>::push_front(&value);
        }

        int removeAll(T &value) {
            return QList<T*>::removeAll(&value);
        }

        void removeAt(int i) {
            QList<T*>::removeAt(i);
        }

        void removeFirst() {
            QList<T*>::removeFirst();
        }

        void removeLast() {
            QList<T*>::removeLast();
        }

        bool removeOne(T &value) {
            return QList<T*>::removeOne(&value);
        }

        void replace(int i, T &value) {
            QList<T*>::replace(i, &value);
        }

        void reserve(int alloc) {
            QList<T*>::reserve(alloc);
        }

        int size() const {
            return QList<T*>::size();
        }

        bool startsWith(T &value) const {
            return QList<T*>::startsWith(&value);
        }

        void swap(ReferenceList<T> &other) {
            QList<T*>::swap(other);
        }

        void swap(int i, int j) {
            QList<T*>::swap(i, j);
        }

        T & takeAt(int i) {
            return *QList<T*>::takeAt(i);
        }

        T & takeFirst() {
            return *QList<T*>::takeFirst();
        }

        T & takeLast() {
            return *QList<T*>::takeLast();
        }

        /**
         * Inherited "to" methods are not supported.
         */
        QSet<T> toSet() const = delete;
        std::list<T> toStdList() const = delete;
        QVector<T> toVector() const = delete;

        T & value(int i) const {
            return *QList<T*>::value(i);
        }

        T & value(int i, T &default_value) const {
            return *QList<T*>::value(i, &default_value);
        }

        bool operator!=(const ReferenceList<T> &other) const {
            return QList<T*>::operator!=(other);
        }

        ReferenceList<T> operator+(const ReferenceList<T> &other) const {
            return ReferenceList<T>(QList<T*>::operator+(other));
        }

        ReferenceList<T> & operator+=(const ReferenceList<T> &other) {
            QList<T*>::operator+=(other);
            return *this;
        }

        ReferenceList<T> & operator+=(T &value) {
            QList<T*>::operator+=(&value);
            return *this;
        }

        ReferenceList<T> & operator<<(const ReferenceList<T> &other) {
            QList<T*>::operator<<(other);
            return *this;
        }

        ReferenceList<T> & operator<<(T &value) {
            QList<T*>::operator<<(&value);
            return *this;
        }

        ReferenceList<T> & operator=(ReferenceList<T> &other) {
            QList<T*>::operator=(other);
            return *this;
        }

        ReferenceList & operator=(ReferenceList<T> &&other) {
            QList<T*>::operator=(std::move(other));
            return *this;
        }

        bool operator==(const ReferenceList<T> &other) const {
            return QList<T*>::operator==(other);
        }

        T & operator[](int i) {
            return *QList<T*>::operator[](i);
        }

        const T & operator[](int i) const {
            return *QList<T*>::operator[](i);
        }


        class iterator : public QList<T*>::iterator {
            public:
                iterator() {  }
                iterator(const typename QList<T*>::iterator &other)
                    : QList<T*>::iterator(other) {  }
                iterator(const iterator &other) : QList<T*>::iterator(other) {  }
                T & operator*() const { return *QList<T*>::iterator::operator*(); }
                T * operator->() const { return *QList<T*>::iterator::operator->(); }
                T & operator[](int j) const { return *QList<T*>::iterator::operator[](j); }
        };

        class const_iterator : public QList<T*>::const_iterator {
            public:
                const_iterator() {  }
                const_iterator(const typename QList<T*>::const_iterator &other)
                    : QList<T*>::const_iterator(other) {  }
                const_iterator(const const_iterator &other)
                    : QList<T*>::const_iterator(other) {  }
                const_iterator(const iterator &other)
                    : QList<T*>::const_iterator(other) {  }
                T & operator*() const { return *QList<T*>::const_iterator::operator*(); }
                T * operator->() const { return *QList<T*>::const_iterator::operator->(); }
                T & operator[](int j) const { return *QList<T*>::const_iterator::operator[](j); }
        };
};


/**
 * Implement QDebug << operator so that it will print out values rather than pointer addresses (do
 * to it implicitly converting to QList<T*>).
 */
template <class T>
QDebug operator<<(QDebug debug, const ReferenceList<T> &list) {
    debug.nospace() << '(';
    for(typename QList<T>::size_type i = 0; i < list.count(); ++i) {
        if(i) debug << ", ";
        debug << list.at(i);
    }

    debug << ')';

    return debug.space();
}


/**
* QDataStream << ReferenceList<T> should have same output as the QDataStream << QList<T>.
*/
template<class T>
QDataStream & operator<<(QDataStream &out, const ReferenceList<T>& list) {
    out << quint32(list.size());
    for(int i = 0; i < list.size(); ++i) out << list.at(i);
    return out;
}


/**
* Make sure QDataStream >> is not callable, there is no scenario where it would be useful with a
* ReferenceList.
*/
template<class T>
QDataStream & operator>>(QDataStream &out, const ReferenceList<T>& list) = delete;

#endif

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何为Orchard Layout创建自定义容器元素?

来自分类Dev

如何为Orchard Layout创建自定义容器元素?

来自分类Dev

如何使用图纸交叉引用创建自定义列表?

来自分类Dev

如何制作自定义容器?

来自分类Dev

引用自定义容器的C ++观察器模式

来自分类Dev

如何使用自定义根卷大小创建Docker容器?

来自分类Dev

如何在symfony2中为自定义类创建服务容器

来自分类Dev

SuiteCRM如何创建类似于“分配给”字段的名为“引用人”的自定义字段?

来自分类Dev

使用布局充气机创建自定义菜单,如何引用每个组件?

来自分类Dev

如何在文档注释中使用自定义链接文本创建代码引用?

来自分类Dev

如何创建自定义形状-CSS

来自分类Dev

如何创建自己的自定义地图

来自分类Dev

如何创建自定义整理器?

来自分类Dev

如何创建自定义SKAction?

来自分类Dev

Jetty如何创建自定义WebSocket

来自分类Dev

如何创建自定义的fabricjs对象?

来自分类Dev

如何创建自定义进度

来自分类Dev

SwiftUI:如何创建自定义UIDatePicker

来自分类Dev

如何创建自定义单选按钮?

来自分类Dev

如何创建自定义后退按钮?

来自分类Dev

如何创建自定义虚线

来自分类Dev

如何创建自定义SELinux标签

来自分类Dev

如何创建自定义模式叠加

来自分类Dev

如何创建自定义的“文档属性”?

来自分类Dev

如何创建自定义JTable?

来自分类Dev

如何创建Django自定义查询?

来自分类Dev

如何创建自定义属性类型

来自分类Dev

如何创建自定义[QUOTE]标签?

来自分类Dev

如何创建自定义吐司