我正在编写一个树结构,我希望将叶节点中的不同数据存储到分支节点。这个想法与动态编程方法非常相似 - 聚合数据存储在分支中。因此我想出了(为简单而减少)
template<class L, class B> class node {
public:
virtual ~node() {}
// [...] visitor stuff
};
template<class L, class B> class branch : public node<L,B> {
public:
template<class It>
branch(It b, It e) {
// Do something with the iterators;
// decide if to create branches or leaves
// Create the branch data
b_ = new B(/* Unknown */);
}
~branch() { delete b_; delete child_[0]; delete child_[1]; }
private:
B* b_; node<L,B>* child_[2];
};
template<class L, class B> class leaf : public node<L,B> {
public:
leaf(L* l) : l_(l) {}
~leaf() {}
private:
L* l_;
};
示例L
和B
结构
struct myleaf { int x; };
struct mybranch {
mybranch(/* Unknown */) {
// Apply a visitor to the child nodes to get sumx
}
int sumx;
// Some other properties
};
我的问题是如何在不遇到B
的循环依赖关系的情况下执行此操作,具体取决于node<L,B>
。或者,我可以轻松地重新构建代码以完全避免这个问题吗?
答案 0 :(得分:1)
据我所见,没有问题。
它基本上是CRTP的一个例子,这是C ++中模板代码的一种相当常见的模式。
当然你可以绊倒编译器,这样就行不通了,但在基础层面,class Derived : Base<Derived>
答案 1 :(得分:0)
我认为你正试图让branch
处理树的行走并获得价值。围绕树走访客的责任应该在树结构中,打破了对结构的依赖。当访问者应用于叶节点时,它将应用它设计的任何操作,当应用于分支时,它可以更新值并执行操作。
为了能够有效地实现这一点,您可能需要向分支/节点内部类型添加一个接口,以提供有关该值是否已经被预先缓存的信息(即不需要沿着树走下去)