在一般情况下,我认为这是不可能的,至少不是干净的。
至少正如通常定义的那样,迭代器期望处理同构集合。即,迭代器通常定义如下:
template <class Element>
class iterator // ...
...因此特定的迭代器只能与一种特定类型的元素一起使用。对于不同类型,您最多可以做的是创建一个指向基类(指针/引用)的迭代器,并让它处理派生类的对象。
相比之下,像这样写一个访问者是很容易的:
class MyVisitor {
public:
void VisitOneType(OneType const *element);
void VisitAnotherType(AnotherType const *element);
};
这可以访问任一OneType
或的节点AnotherType
,即使两者完全不相关。基本上,您Visit
的 Visitor 类中有一个成员函数,用于它能够访问的每种不同类型的类。
从稍微不同的方向来看,迭代器基本上是一种特殊形式的访问者,仅适用于一种类型的对象。您交换了对访问模式的更多控制权,以换取失去访问不相关类型对象的能力。
如果您只需要处理一种类型(尽管一种类型可能是基类,并且访问的对象是各种派生类型),那么显而易见的方法是构建一个访问对象(Tree
节点,在你的例子中),当它visit
被调用时,它只是将它正在访问的节点的地址复制到一些支持迭代器的集合中:
template <class T>
class Bridge {
std::vector<T *> nodes;
public:
virtual void visit(T *n) {
nodes.push_back(n);
}
typedef std::vector<T *>::iterator iterator;
iterator begin() { return nodes.begin(); }
iterator end() { return nodes.end(); }
};
使用这将是一个两步过程:首先像访问者一样访问节点,然后将感兴趣的节点收集在一起,您可以像访问任何其他提供迭代器的集合一样遍历它们。此时,您的访问模式仅受您在网桥中使用的集合提供的迭代器类的限制。