12

私はSTLのようなイテレータを実装したことがなく、ポインタに基づいて非常に基本的なものを実装する方法を理解しようとしています。このクラスを取得すると、より複雑なことを行うように変更できるようになります。したがって、これは最初のステップであり、(ブーストなしで)独自のイテレーターを作成する方法を理解するには、堅実である必要があります。

私は次のコードを書きましたが、エラーがあることを知っています。そこから着想を得たランダムアクセスイテレータクラスを正しく設計するのを手伝ってもらえますか?

template<Type> class Container<Type>::Iterator : public std::iterator<random_access_iterator_tag, Type>
{
    // Lifecycle:
    public:
        Iterator() : _ptr(nullptr) {;}
        Iterator(Type* rhs) : _ptr(rhs) {;}
        Iterator(const Iterator &rhs) : _ptr(rhs._ptr) {;}

    // Operators : misc
    public:
        inline Iterator& operator=(Type* rhs) {_ptr = rhs; return *this;}
        inline Iterator& operator=(const Iterator &rhs) {_ptr = rhs._ptr; return *this;}
        inline Iterator& operator+=(const int& rhs) {_ptr += rhs; return *this;}
        inline Iterator& operator-=(const int& rhs) {_ptr -= rhs; return *this;}
        inline Type& operator*() {return *_ptr;}
        inline Type* operator->() {return _ptr;}
        inline Type& operator[](const int& rhs) {return _ptr[rhs];}

    // Operators : arithmetic
    public:
        inline Iterator& operator++() {++_ptr; return *this;}
        inline Iterator& operator--() {--_ptr; return *this;}
        inline Iterator& operator++(int) {Iterator tmp(*this); ++_ptr; return tmp;}
        inline Iterator& operator--(int) {Iterator tmp(*this); --_ptr; return tmp;}
        inline Iterator operator+(const Iterator& rhs) {return Iterator(_ptr+rhs.ptr);}
        inline Iterator operator-(const Iterator& rhs) {return Iterator(_ptr-rhs.ptr);}
        inline Iterator operator+(const int& rhs) {return Iterator(_ptr+rhs);}
        inline Iterator operator-(const int& rhs) {return Iterator(_ptr-rhs);}
        friend inline Iterator operator+(const int& lhs, const Iterator& rhs) {return Iterator(lhs+_ptr);}
        friend inline Iterator operator-(const int& lhs, const Iterator& rhs) {return Iterator(lhs-_ptr);}

    // Operators : comparison
    public:
        inline bool operator==(const Iterator& rhs) {return _ptr == rhs._ptr;}
        inline bool operator!=(const Iterator& rhs) {return _ptr != rhs._ptr;}
        inline bool operator>(const Iterator& rhs) {return _ptr > rhs._ptr;}
        inline bool operator<(const Iterator& rhs) {return _ptr < rhs._ptr;}
        inline bool operator>=(const Iterator& rhs) {return _ptr >= rhs._ptr;}
        inline bool operator<=(const Iterator& rhs) {return _ptr <= rhs._ptr;}

    // Data members
    protected:
        Type* _ptr;
};

どうもありがとうございます。

4

3 に答える 3

14

コードには次の問題があります。

  • あなたは三つのルールに従わない。状況に応じた最善のオプションは、カスタムデストラクタ、コピー/ムーブコンストラクタ、またはコピー/ムーブ代入演算子を宣言しないことです。いわゆるゼロのルールに従いましょう。
  • Iterator(Type* rhs) プライベートである可能Container性があり、の友人としてマークされる可能性がありますIteratorが、それは厳密には必要ではありません。
  • operator=(Type* rhs)悪い考えです。それは型安全性についてではありません。
  • Post-in(de)crementationはIterator、ではなく、を返す必要がありIterator &ます。
  • 2つのイテレータを追加しても意味がありません。
  • 2つのイテレータを減算すると、新しいイテレータではなく、差が返されます。
  • std::iterator<std::random_access_iterator_tag, Type>::difference_typeの代わりに使用する必要がありconst int &ます。
  • メソッドがオブジェクトを変更しない場合は、マークを付ける必要がありますconst

有用なリソース:RandomAccessIterator @ cppreference.com

コードの修正バージョンは次のとおりです。

template<typename Type>
class Container<Type>::Iterator : public std::iterator<std::random_access_iterator_tag, Type>
{
public:
    using difference_type = typename std::iterator<std::random_access_iterator_tag, Type>::difference_type;
    
    Iterator() : _ptr(nullptr) {}
    Iterator(Type* rhs) : _ptr(rhs) {}
    Iterator(const Iterator &rhs) : _ptr(rhs._ptr) {}
    /* inline Iterator& operator=(Type* rhs) {_ptr = rhs; return *this;} */
    /* inline Iterator& operator=(const Iterator &rhs) {_ptr = rhs._ptr; return *this;} */
    inline Iterator& operator+=(difference_type rhs) {_ptr += rhs; return *this;}
    inline Iterator& operator-=(difference_type rhs) {_ptr -= rhs; return *this;}
    inline Type& operator*() const {return *_ptr;}
    inline Type* operator->() const {return _ptr;}
    inline Type& operator[](difference_type rhs) const {return _ptr[rhs];}
    
    inline Iterator& operator++() {++_ptr; return *this;}
    inline Iterator& operator--() {--_ptr; return *this;}
    inline Iterator operator++(int) const {Iterator tmp(*this); ++_ptr; return tmp;}
    inline Iterator operator--(int) const {Iterator tmp(*this); --_ptr; return tmp;}
    /* inline Iterator operator+(const Iterator& rhs) {return Iterator(_ptr+rhs.ptr);} */
    inline difference_type operator-(const Iterator& rhs) const {return _ptr-rhs.ptr;}
    inline Iterator operator+(difference_type rhs) const {return Iterator(_ptr+rhs);}
    inline Iterator operator-(difference_type rhs) const {return Iterator(_ptr-rhs);}
    friend inline Iterator operator+(difference_type lhs, const Iterator& rhs) {return Iterator(lhs+rhs._ptr);}
    friend inline Iterator operator-(difference_type lhs, const Iterator& rhs) {return Iterator(lhs-rhs._ptr);}
    
    inline bool operator==(const Iterator& rhs) const {return _ptr == rhs._ptr;}
    inline bool operator!=(const Iterator& rhs) const {return _ptr != rhs._ptr;}
    inline bool operator>(const Iterator& rhs) const {return _ptr > rhs._ptr;}
    inline bool operator<(const Iterator& rhs) const {return _ptr < rhs._ptr;}
    inline bool operator>=(const Iterator& rhs) const {return _ptr >= rhs._ptr;}
    inline bool operator<=(const Iterator& rhs) const {return _ptr <= rhs._ptr;}
private:
    Type* _ptr;
};
  
于 2015-08-07T20:53:49.510 に答える
2

一般的に、あなたのアプローチは正しいです。接尾辞のインクリメント/デクリメント演算子は、参照ではなく値で返す必要があります。私も疑問を持っています:

Iterator(Type* rhs) : _ptr(rhs) {;}

これは、このイテレータクラスがポインタの周りに実装されていることをすべての人に伝えます。このメソッドをコンテナからのみ呼び出し可能にしようと思います。ポインタへの割り当てについても同じです。2つのイテレータを追加しても意味がありません(「iterator + int」のままにします)。同じコンテナを指す2つのイテレータを差し引くことは、ある程度意味があるかもしれません。

于 2012-08-23T13:31:45.200 に答える
2

Boostがどのようにそれを行うか、boost / container / vector.hppのイテレーターを見てください-vector_const_iteratorそして、vector_iteratorポインターベースのイテレーターを理解するのはかなり簡単です。

于 2012-08-23T13:31:55.027 に答える