迭代器继承和继承* this [英] Iterator Inheritance and inheriting *this

查看:146
本文介绍了迭代器继承和继承* this的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何编写一个基类和多个派生类的迭代器?



迭代器是否必须返回自己? b

到目前为止,我使用 typename X static_cast< X&>(* this)允许派生类继承一个从基类返回自身的函数。



这个看起来很丑。有更好的方法吗?



简化代码:

  #include < iterator> 
#include< iostream>
template< typename T,typename X>
class BaseIterator:public std :: iterator< std :: input_iterator_tag,T> {
//不可直接使用。
private:
T * p;
protected:
virtual void increment(void)= 0;
virtual T * stride_index(int index)= 0;
public:
virtual〜BaseIterator(){} //虚拟析构函数。
X operator ++(int){//取一个虚int参数
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>它(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 * b BaseIterator(T * x):p(x){}
public:
X operator ++(int){//获取一个虚拟int参数
X tmp
self() - > increment();
return tmp;
}
bool operator ==(const X& rhs)const {return p == rhs.p; }
};

基数通常采用派生类型,加上函数 signatures 作为模板参数。然后你添加两个 self()函数,它给你的派生类型,这意味着你不需要 virtual 。一切都由编译器内联。 (注意我也给它一个合理的构造函数,并使 operator == const

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

$ b b

然后派生类型继承正常,除非你必须使用 this-> 来访问成员,因为父类是模板。请参见此处: http://coliru.stacked-crooked.com/a/81182d994c7edea7



这产生了一个高效的迭代器,没有开销。我相信这种技术在Boost的迭代器库中使用相当多: http://www.boost.org/doc/libs/1_59_0/libs/iterator/doc/#new-style-iterators


How to write a base class and several derived classes of iterator?

Does the iterator have to return itself (*this)?

So far, I use typename X and static_cast<X&>(*this) to allow the derived class to inherit a function that return itself from the base class.

This looks ugly. Is there a better way?

Simplified Code:

#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;
}

The alternative is to forget about using inheritance to write less code. Just copy and paste the function that return *this to the derived classes.

That alternative seems increasingly acceptable to me ...

解决方案

Generally, virtual is a lot of overhead for something like iterators which ought to be lightweight. The usual way to go is CRTP. Which is a little tricky, but looks like this:

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; }
} ;

The base usually takes the derived type, plus whatever it needs for function signatures as template parameters. Then you add two self() functions, which give you the derived type, which means you don't actually need virtual. Everything is trivially inlined by the compiler. (Note I've also given it a sane constructor, and made 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) {}
} ;

Then the derived type simply inherits as normal, except you have to use this-> to access the member, since the parent is a template. See it working here: http://coliru.stacked-crooked.com/a/81182d994c7edea7

This produces a highly efficient iterator, with no overhead. I believe this technique is used quite heavily in Boost's iterator library: http://www.boost.org/doc/libs/1_59_0/libs/iterator/doc/#new-style-iterators

这篇关于迭代器继承和继承* this的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆