| 作者 | David Abrahams, Jeremy Siek, Thomas Witt |
|---|---|
| 联系方式 | dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de |
| 组织 | Boost Consulting, 印第安纳大学 Open Systems Lab, 汉诺威大学 运输铁路运营与建设研究所 |
| 日期 | 2006-09-11 |
| 版权 | Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. |
| 摘要 |
|---|
Each specialization of theiterator_adaptorclass template is derived from a specialization ofiterator_facade. The core interface functions expected byiterator_facadeare implemented in terms of theiterator_adaptor的Basetemplate parameter. A class derived fromiterator_adaptortypically redefines some of the core interface functions to adapt the behavior of theBasetype. Whether the derived class models any of the standard iterator concepts depends on the operations supported by theBasetype and which core interface functions ofiterator_facadeare redefined in theDerivedclass.
目录
该iterator_adaptorclass template adapts someBase1 类型以创建新的迭代器。其实例化iterator_adaptorare derived from a corresponding instantiation ofiterator_facadeand implement the core behaviors in terms of theBasetype. In essence,iterator_adaptormerely forwards all operations to an instance of theBasetype, which it stores as a member.
| [1] | (1, 2) 此处的“Base”(基)一词并不指代基类,也不意味着使用派生。我们沿用了标准库的做法,标准库提供了一个 base() 函数来访问底层的迭代器对象reverse_iteratoradaptor. |
The user ofiterator_adaptorcreates a class derived from an instantiation ofiterator_adaptorand then selectively redefines some of the core member functions described in theiterator_facadecore requirements table. TheBasetype need not meet the full requirements for an iterator; it need only support the operations used by the core interface functions ofiterator_adaptorthat have not been redefined in the user's derived class.
Several of the template parameters ofiterator_adaptordefault touse_default的底层迭代器对象。这允许用户即使希望稍后在参数列表中指定参数,也可以使用默认参数。此外,相应关联类型的默认值有些复杂,因此需要元编程来计算它们,并且use_defaultcan help to simplify the implementation. Finally, the identity of theuse_defaulttype is not left unspecified because specification helps to highlight that the参考template parameter may not always be identical to the iterator'sreferencetype, and will keep users from making mistakes based on that assumption.
template <
class Derived
, class Base
, class Value = use_default
, class CategoryOrTraversal = use_default
, class Reference = use_default
, class Difference = use_default
>
class iterator_adaptor
: public iterator_facade<Derived, V', C', R', D'> // see details
{
friend class iterator_core_access;
public:
iterator_adaptor();
explicit iterator_adaptor(Base const& iter);
typedef Base base_type;
Base const& base() const;
protected:
typedef iterator_adaptor iterator_adaptor_;
Base const& base_reference() const;
Base& base_reference();
private: // Core iterator interface for iterator_facade.
typename iterator_adaptor::reference dereference() const;
template <
class OtherDerived, class OtherIterator, class V, class C, class R, class D
>
bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
void advance(typename iterator_adaptor::difference_type n);
void increment();
void decrement();
template <
class OtherDerived, class OtherIterator, class V, class C, class R, class D
>
typename iterator_adaptor::difference_type distance_to(
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
private:
Base m_iterator; // exposition only
};
static_cast<Derived*>(iterator_adaptor*)shall be well-formed. TheBaseargument shall be Assignable and Copy Constructible.
The V', C', R', and D' parameters of theiterator_facadeused as a base class in the summary ofiterator_adaptorabove are defined as follows
V' = if (Value is use_default)
return iterator_traits<Base>::value_type
else
return Value
C' = if (CategoryOrTraversal is use_default)
return iterator_traversal<Base>::type
else
return CategoryOrTraversal
R' = if (Reference is use_default)
if (Value is use_default)
return iterator_traits<Base>::reference
else
return Value&
else
return Reference
D' = if (Difference is use_default)
return iterator_traits<Base>::difference_type
else
return Difference
iterator_adaptor();
| 要求 | 该Basetype must be Default Constructible. |
|---|---|
| 返回 | 的一个实例iterator_adaptor带有m_iterator默认构造。 |
explicit iterator_adaptor(Base const& iter);
| 返回 | 的一个实例iterator_adaptor带有m_iterator从...复制构造iter. |
|---|
Base const& base() const;
| 返回 | m_iterator |
|---|
Base const& base_reference() const;
| 返回 | A const reference tom_iterator. |
|---|
Base& base_reference();
| 返回 | A non-const reference tom_iterator. |
|---|
typename iterator_adaptor::reference dereference() const;
| 返回 | *m_iterator |
|---|
template < class OtherDerived, class OtherIterator, class V, class C, class R, class D > bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
| 返回 | m_iterator == x.base() |
|---|
void advance(typename iterator_adaptor::difference_type n);
| 效果 | m_iterator += n; |
|---|
void increment();
| 效果 | ++m_iterator; |
|---|
void decrement();
| 效果 | --m_iterator; |
|---|
template <
class OtherDerived, class OtherIterator, class V, class C, class R, class D
>
typename iterator_adaptor::difference_type distance_to(
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
| 返回 | y.base() - m_iterator |
|---|
在本节中,我们将进一步完善node_iter我们在 iterator_facade 教程 中开发的类模板。如果你还没读过该材料,建议先回头阅读,因为我们将从之前中断的地方继续。
你可能没这么想过,但node_base*对象,即node_iterator的基础,本身就是一个迭代器,就像所有其他指针一样。如果我们从迭代器的角度仔细审视那个指针,就会发现它与我们正在构建的node_iterator有很多共同之处。首先,它们共享大部分相同的关联类型(value_type, reference, pointer和difference_type)。其次,甚至一些核心功能也是相同的operator*andoperator==在node_iterator上执行的操作返回的是调用底层指针上相同操作的结果,通过node_iterator的 dereference 和 equal 成员函数)。它们之间唯一真正的行为差异node_base*andnode_iterator可以在它们递增时观察到node_iterator遵循m_next指针,而node_base*仅仅应用了一个地址偏移量。
事实证明,在另一种类似于迭代器的类型(即Base1 类型)之上构建迭代器,同时只修改底层类型的一小部分行为,是一种非常常见的模式,这正是iterator_adaptor所要解决的模式。使用iterator_adaptor非常类似于使用iterator_facade,但因为 iterator_adaptor 尝试尽可能模拟Base类型的行为,我们既不需要提供值参数,也不需要实现除increment之外的任何核心行为。因此,node_iter的实现简化为
template <class Value>
class node_iter
: public boost::iterator_adaptor<
node_iter<Value> // Derived
, Value* // Base
, boost::use_default // Value
, boost::forward_traversal_tag // CategoryOrTraversal
>
{
private:
struct enabler {}; // a private type avoids misuse
public:
node_iter()
: node_iter::iterator_adaptor_(0) {}
explicit node_iter(Value* p)
: node_iter::iterator_adaptor_(p) {}
template <class OtherValue>
node_iter(
node_iter<OtherValue> const& other
, typename boost::enable_if<
boost::is_convertible<OtherValue*,Value*>
, enabler
>::type = enabler()
)
: node_iter::iterator_adaptor_(other.base()) {}
private:
friend class boost::iterator_core_access;
void increment() { this->base_reference() = this->base()->next(); }
};
请注意这里使用了node_iter::iterator_adaptor_:因为iterator_adaptor定义了一个嵌套的iterator_adaptor_类型,该类型指向其自身,这为我们提供了一种便捷的方式来引用node_iter<Value>的复杂基类类型。[注:已知该技术在 Borland C++ 5.6.4 和 9.0 版本之前的 Metrowerks CodeWarrior 中无法使用]
你可以在此处查看练习此版本节点迭代器的示例程序。
对于node_iter来说,传递boost::use_default和iterator_adaptor的值参数并不是很有说服力;我们本可以直接将node_iter的值传给iterator_adaptor,那样甚至更短!大多数使用iterator_adaptor构建的迭代器类模板是基于另一种迭代器类型进行参数化的,而不是基于其value_type。例如,boost::reverse_iterator接收一个迭代器类型参数并反转其遍历方向,由于原始迭代器和反转后的迭代器具有所有相同的关联类型,iterator_adaptor将默认类型委托给其Base,从而使boost::reverse_iterator的实现者无需编写
std::iterator_traits<Iterator>::some-associated-type
至少四次。
我们强烈建议你查阅 reverse_iterator 以及其他 Boost 专用迭代器适配器 的文档和实现,以了解你可以用iterator_adaptor做些什么。特别是,请看一看 transform_iterator,它可能是最直观的适配器,还有 counting_iterator,它证明了iterator_adaptor的Base类型不一定非得是迭代器。