Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为泛型树定义迭代器_C++_Templates_Tree_Generic Programming - Fatal编程技术网

C++ 为泛型树定义迭代器

C++ 为泛型树定义迭代器,c++,templates,tree,generic-programming,C++,Templates,Tree,Generic Programming,我有一个叫做“节点”的类。我一直在考虑把它改名为“树”,但两个名字都有同样的意义。此类实现了一个通用树容器。每个节点可以有任意数量的子节点。该类的基本标题定义如下: template<class Elem> class Node { public: Node(); ~Node(); Node(const Elem& value); Node(const Node& rNode); const Elem& operator

我有一个叫做“节点”的类。我一直在考虑把它改名为“树”,但两个名字都有同样的意义。此类实现了一个通用树容器。每个节点可以有任意数量的子节点。该类的基本标题定义如下:

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;
};
模板
类节点
{
公众:
Node();
~Node();
节点(常量和值);
节点(const节点和rNode);
常量和运算符*()常量;
电子及操作员*();
元素*运算符->();
无效运算符=(常量元素和rhs);
节点*添加子节点(常量元素和值);
Node*addChild(Node-childNode);
节点*addChild(节点*pChildNode);
HRESULT removeNode(DFSIerator&iter);
模板友元类DFS迭代器;
私人:
布尔hasChild()常量;
节点*m_pParentNode;
元素m_值;
std::向量m_childList;
静态标准::设置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;
};
模板
类迭代器
{
公众:
DFSIterator(项和节点);
~DFSIterator();
DFSIterator*begin();
DFSIterator*运算符++();
项目和操作员*()常数;
项*运算符->()常量;
布尔运算符!=(常量DFSIterator&rhs)常量;
bool isDone()常量;
运算符bool()常量{return!isDone();}
私人:
模板好友类节点;
void initChildListIterator(项*currentNode);
布尔·穆比斯敦;
项目*m_pRootNode;
项目*m_pCurrentNode;
ChildListIterator*m_pCurrentListIter;
std::map m_listMap;
};
是节点的迭代器别名

我遇到的问题是,我想为这棵树定义迭代器,用户可以用类似于STL容器的方式声明迭代器。我想把typedef语句放在像
typedef DFSIterator dfs\u iterator可以正常工作。但每当我将这些语句添加到头中时,就会出现以下错误
error C2512:没有合适的默认构造函数可用。
无论我在哪里尝试使用它

所以现在,要声明迭代器,我必须执行类似于
DFSIterator dfsIter=rRootNode.begin()的操作或<代码>DFSIterator dfsIter(rNode)如果我不想从树的根节点开始。我希望能够做的事情更像是
Node::dfs\u iterator it=rRootNode.begin()
。有没有一种方法是我所缺少的


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

如果在节点内定义dfs\u迭代器,则基本上可以像您描述的那样使用它:

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:

    .
    .
    .
};
模板
类节点
{
公众:
typedef节点项;
模板<
类列表=标准::向量,
类Iter=typename std::vector::iterator
>类dfs_迭代器;
.
.
.
};
模板
模板
类节点::dfs\U迭代器
{
公众:
.
.
.
};
和使用

Node<DataMap>::dfs_iterator<> it = rRootNode.begin();
Node::dfs\u迭代器it=rRootNode.begin();

唯一的区别是,由于dfs_迭代器是一个模板,因此您必须指定模板参数,即使它们都可以是默认的。

如果您在节点内定义dfs_迭代器,则基本上可以像您描述的那样使用它:

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:

    .
    .
    .
};
模板
类节点
{
公众:
typedef节点项;
模板<
类列表=标准::向量,
类Iter=typename std::vector::iterator
>类dfs_迭代器;
.
.
.
};
模板
模板
类节点::dfs\U迭代器
{
公众:
.
.
.
};
和使用

Node<DataMap>::dfs_iterator<> it = rRootNode.begin();
Node::dfs\u迭代器it=rRootNode.begin();

唯一的区别是,因为dfs_迭代器是一个模板,所以您必须指定模板参数,即使它们都可以是默认的。

您看过Boost.Graph库吗?我看过。在他们的文档中,我似乎找不到任何东西可以为我指明正确的方向。在BGL中,他们将迭代器和访问者的概念分开,您选择将它们组合在一起。您可以定义一个VertexListGraph,并使用DFS访问者对其执行DepthFirst搜索。在
节点内定义
DFSIterator
如何?@rhalbersma感谢您的提示。我肯定会更深入地研究访问者模式。你看过Boost.Graph库吗?我看过。在他们的文档中,我似乎找不到任何东西可以为我指明正确的方向。在BGL中,他们将迭代器和访问者的概念分开,您选择将它们组合在一起。您可以定义一个VertexListGraph,并使用DFS访问者对其执行DepthFirst搜索。在
节点内定义
DFSIterator
如何?@rhalbersma感谢您的提示。我肯定会更深入地研究访问者模式。我之前确实尝试过这样做,但看起来我只是做了错误的语法。我来试一试。谢谢我最终确实把这些类嵌套起来了。我放弃了列表和Iter模板,因为它们给设计带来了很多麻烦,似乎不需要它们。我不太清楚为什么我一开始就有这些。我知道曾经有一个目的。我之前确实尝试过这样做,但看起来我只是做了错误的语法。我来试一试。谢谢我最终确实把这些类嵌套起来了。我放弃了列表和Iter模板,因为它们给设计带来了很多麻烦,似乎不需要它们。我不太清楚为什么我一开始就有这些。我知道曾经有一个目的。