定义通用树的迭代器

时间:2013-01-23 15:23:36

标签: c++ templates tree generic-programming

我有这个名为“Node”的类。我一直在考虑将其重命名为“Tree”,但两种名称都具有同样的意义。此类实现通用树容器。每个节点可以有任意数量的子节点。该类的基本头定义如下:

template<class Elem>
class Node
{
public:
    Node();
    ~Node();
    Node(const Elem& value);
    Node(const Node& rNode);
    const Elem& operator*() const;
    Elem& operator*();
    Elem* operator->();
    void operator=(const Elem& rhs);
    Node* addChild(const Elem& value);
    Node* addChild(Node childNode);
    Node* addChild(Node* pChildNode);
    HRESULT removeNode(DFSIterator<Node>& iter);

    template <class Node, class List, class Iter> friend class DFSIterator;

private:
    bool hasChild() const;

    Node* m_pParentNode;
    Elem m_value;
    std::vector<Node*> m_childList;
    static std::set<Node*> sNodeSet;
};

我的DFSIterator的标头定义是:

template<class Item, 
         class List = std::vector<Item*>, 
         class Iter = typename std::vector<Item*>::iterator>
class DFSIterator
{
public:
    DFSIterator(Item& rRootNode);
    ~DFSIterator();
    DFSIterator* begin();
    DFSIterator* operator++();
    Item& operator*() const;
    Item* operator->() const;
    bool operator!=(const DFSIterator& rhs) const;
    bool isDone() const;
    operator bool() const {return !isDone();}

private:
    template <class Node> friend class Node;

    void initChildListIterator(Item* currentNode);

    bool m_bIsDone;
    Item* m_pRootNode;
    Item* m_pCurrentNode;
    ChildListIterator<Item>* m_pCurrentListIter;
    std::map<Item*, ChildListIterator<Item, List, Iter>*>  m_listMap;
};

ItemNode<Elem>的迭代器别名。

我遇到的问题是我想为这个树定义迭代器,用户可以用类似于STL容器的方式声明它。我认为像typedef DFSIterator<Node<Elem>> dfs_iterator;这样放置typedef语句会很好。但每当我将这些语句添加到标题中时,我都会收到以下错误error C2512<Item>: no appropriate default constructor available.无论我在哪里尝试使用它。

现在,要声明迭代器,如果我不想从树的根节点开始,我必须执行DFSIterator<Node<DataMap>> dfsIter = rRootNode.begin();DFSIterator<Node<DataMap>> dfsIter(rNode);之类的操作。我希望能够做的更像是Node<DataMap>::dfs_iterator it = rRootNode.begin()。有没有办法做到这一点,我错过了?

注意:我确实想要更改有关此实现的其他一些内容。我真的不希望用户将节点元素传递给addChild()方法。我宁愿让用户传递一个指向节点的迭代器。

1 个答案:

答案 0 :(得分:1)

如果你在Node中定义dfs_iterator,那么你可以像你描述的那样使用它:

template<class Elem>
class Node
{
public:
    typedef Node<Elem> Item;

    template<
        class List = std::vector<Item*>, 
        class Iter = typename std::vector<Item*>::iterator
    > class dfs_iterator;

     .
     .
     .
};

template<class Elem>
template<class List, class Iter>
class Node<Elem>::dfs_iterator
{
public:

    .
    .
    .
};

并使用

Node<DataMap>::dfs_iterator<> it = rRootNode.begin();

唯一的区别是,由于dfs_iterator是一个模板,你必须指定模板参数,即使它们都可以默认。