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模板,因为它们给设计带来了很多麻烦,似乎不需要它们。我不太清楚为什么我一开始就有这些。我知道曾经有一个目的。