迭代器继承与继承*this
Iterator Inheritance and inheriting *this
如何编写一个基础 class 和几个派生的 class 迭代器?
迭代器是否必须 return 本身 (*this)?
到目前为止,我使用 typename X
和 static_cast<X&>(*this)
来允许派生 class 从基 class 继承 return 本身的函数。
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;
}
另一种方法是忘记使用继承来编写更少的代码。只需将 return *this
的函数复制并粘贴到派生的 classes.
我似乎越来越能接受这个替代方案...
一般来说,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; }
} ;
基础通常采用派生类型,加上函数 signatures 所需的任何内容作为模板参数。然后你添加两个 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
如何编写一个基础 class 和几个派生的 class 迭代器?
迭代器是否必须 return 本身 (*this)?
到目前为止,我使用 typename X
和 static_cast<X&>(*this)
来允许派生 class 从基 class 继承 return 本身的函数。
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;
}
另一种方法是忘记使用继承来编写更少的代码。只需将 return *this
的函数复制并粘贴到派生的 classes.
我似乎越来越能接受这个替代方案...
一般来说,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; }
} ;
基础通常采用派生类型,加上函数 signatures 所需的任何内容作为模板参数。然后你添加两个 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