2014-10-11 4 views
1

Disclamer가 :참조의 사용자 지정 컨테이너를 만드는 방법은 무엇입니까?

나는 이미 C++에서위원회는이를 지원하지 않는 이유가없는거야, 그래서, 또는 다른 어떤 종류의 "이 나쁜 생각"말해 아무 대답, 나는 대부분에 싶지하십시오 이해 재미로이 작업을 수행하고, 개인적으로 사용하고 싶은 상황을 발견했습니다. 프로그래머는 항상 이런 유형의 것에 대해 논쟁 할 것이기 때문에 논쟁의 여지가 없다.

Qestion : ... 난 단지 C++는 참조의 컨테이너를 지원하지 않는 것을 발견하기 위해, QList를 사용하고자하는, 그래서 내가 생각했던 점에 지금

어쩌면 사용자 지정 컨테이너를 만들 수 있습니다 실제로 후드 아래에 포인터를 저장 한 참조 (본질적으로 어떤 참조가 본질적으로 후드 아래에 있는지)입니다. 이 일을하는 가장 좋은 방법은 무엇입니까?

내가 구현 작업을 얻을 수 있었다, 나는 생각 : 대답

(! 그리고 난의 열린 생각을 가진 사람이 될 수 있도록, 답변으로 "그것을 할 수있는 더 좋은 방법이 없다"수락하지 않습니다) 그것은 꽤 잘 작동합니다, 나는 QList를 사용하지만 개념은 모든 컨테이너 유형에 대해 동일해야합니다. 여기에 Github Gist를 만들었습니다 : ReferenceList.hpp. 또는 아래 답변에서 확인할 수 있습니다.

비록 내 자신의 질문에 대답했지만, 이것을 달성하는 방법에 대한 다른 아이디어를 게시하는 것을 두려워하지 마십시오!

+0

여기에 질문이 있습니까? –

+0

아니요, 저는이 문제에 대한 해결책을 공유하고 싶습니다. 여기 규칙에 어긋나지 않아? – Tory

+1

질문을 마치 묻는 것처럼 질문을 작성하고 답을 답으로 써야합니다. 다른 사람이 대답 할 수도있는 관점에서 본 질문 텍스트를 생각해보십시오. – hyde

답변

2
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
* 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 
+0

구현을 완전히 철저히 조사 했으므로 지금은 완벽하게 작동해야합니다. – Tory

관련 문제