簡體   English   中英

迭代器繼承和繼承 *this

[英]Iterator Inheritance and inheriting *this

迭代器的一個基類和幾個派生類怎么寫?

迭代器是否必須返回自身(*this)?

到目前為止,我使用typename Xstatic_cast<X&>(*this)來允許派生類繼承一個從基類返回自身的函數。

This看起來很丑。 有沒有更好的辦法?

簡化代碼:

#include <iterator>
#include <iostream>
template <typename T, typename X>
class BaseIterator : public std::iterator<std::input_iterator_tag, T> {
    //Not intended to be used directly.
    private:
        T* p;
    protected:
        virtual void increment(void)=0;
        virtual T* stride_index(int index)=0;
    public:
        virtual ~BaseIterator(){} //virtual destructor.
        X operator++(int) { //takes a dummy int argument
            X tmp(static_cast<X&>(*this) );
            increment();
            return tmp;
        }
        bool operator==(const X & rhs) { return p==rhs.p; }
} ;
template <typename T>
class ContiguousIterator : public BaseIterator<T, ContiguousIterator<T> > {
    private:
        T* p;
    protected:
        inline void increment(void) {++p;}
        inline T* stride_index(int index){return p + index;}
    public:
        virtual ~ContiguousIterator(){} //destructor.
        ContiguousIterator(T* x) :p(x) {}
        ContiguousIterator(const ContiguousIterator<T> & mit) : p(mit.p) {}
} ;

int main(void){
    int i[]={0,1,2,3,4,5};
    ContiguousIterator<int> itbegin(i);
    ContiguousIterator<int> it(i);
    it++;
    std::cout << "result: " << (it == itbegin) << std::endl;
}

另一種方法是忘記使用繼承來編寫更少的代碼。 只需將返回*this的函數復制並粘貼到派生類即可。

這種選擇似乎越來越為我所接受......

一般來說,對於應該是輕量級的迭代器之類的東西來說, virtual是很多開銷。 通常的方法是CRTP。 這有點棘手,但看起來像這樣:

template <typename T, typename X>
class BaseIterator : public std::iterator<std::input_iterator_tag, T> {
    protected:
        T* p;
        X* self() {return static_cast<X*>(this);}
        const X* self() const {return static_cast<const X*>(this);}
        BaseIterator(T* x) :p(x) {}
    public:
        X operator++(int) { //takes a dummy int argument
            X tmp(*self());
            self()->increment();
            return tmp;
        }
        bool operator==(const X & rhs) const { return p==rhs.p; }
} ;

基類通常采用派生類型,加上函數簽名所需的任何內容作為模板參數。 然后添加兩個self()函數,它們為您提供派生類型,這意味着您實際上並不需要virtual 一切都由編譯器簡單地內聯。 (注意我還給了它一個健全的構造函數,並制作了operator== const

template <typename T>
class ContiguousIterator : public BaseIterator<T, ContiguousIterator<T> > {
    public:
        typedef BaseIterator<T, ContiguousIterator<T> > parent;
        void increment(void) {++(this->p);}
        T* stride_index(int index) const {return this->p + index;}
    public:
        virtual ~ContiguousIterator(){} //destructor.
        ContiguousIterator(T* x) :parent(x) {}
        ContiguousIterator(const ContiguousIterator<T> & mit) : parent(mit.p) {}
} ;

然后派生類型只是照常繼承,除非您必須使用this->來訪問成員,因為父類型是模板。 看到它在這里工作: http : //coliru.stacked-crooked.com/a/81182d994c7edea7

這會產生一個高效的迭代器,沒有開銷。 我相信這種技術在 Boost 的迭代器庫中被大量使用: http : //www.boost.org/doc/libs/1_59_0/libs/iterator/doc/#new-style-iterators

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM