Reputation: 5142
I'm trying to build a binary tree with smart pointers, where nodes also include a parent pointer. To do that, I defined the children pointers as shared_ptr
and the parent pointers as weak_ptr
.
The best I could come up with is the following:
#include <iostream>
#include <memory>
using namespace std;
struct Node;
struct NodeBase {
int val;
NodeBase(int v) : val(v) {}
virtual void add_node_left(shared_ptr<Node> &ptr, int v) = 0;
virtual void add_node_right(shared_ptr<Node> &ptr, int v) = 0;
virtual ~NodeBase() {};
};
struct NodePtr {
shared_ptr<NodeBase> ptr;
template<typename... Args>
NodePtr(Args&&... args) : ptr(std::forward<Args>(args)...) {}
void add_left(int v) {
shared_ptr<Node> node_ptr = std::static_pointer_cast<Node>(ptr);
ptr->add_node_left(node_ptr, v);
}
void add_right(int v) {
shared_ptr<Node> node_ptr = std::static_pointer_cast<Node>(ptr);
ptr->add_node_right(node_ptr, v);
}
};
struct Node : public NodeBase {
NodePtr left, right;
weak_ptr<Node> parent;
Node(int v) : NodeBase(v), left(nullptr), right(nullptr), parent() {}
shared_ptr<Node> make_child(shared_ptr<Node> &selfptr, int v) {
auto child = make_shared<Node>(v);
child->parent = selfptr;
return child;
}
void virtual add_node_left(shared_ptr<Node> &selfptr, int v) {
left = make_child(selfptr, v);
}
void virtual add_node_right(shared_ptr<Node> &selfptr, int v) {
right = make_child(selfptr, v);
}
virtual ~Node() {};
};
struct Tree {
NodePtr root;
Tree() : root(nullptr) {};
Tree(int val) {
add_root(val);
}
void add_root(int val) {
root = make_shared<Node>(val);
}
};
int main() {
Tree tree;
tree.add_root(10);
tree.root.add_left(5);
tree.root.add_right(12);
}
First of all, is this correct?
Second, I'm not very fond of having to define the NodeBase
base class. The reason for it is so I can pass the shared_ptr
to add_node_left
and add_node_right
, needed to create the parent weak_ptr
. Is there a way to do this that avoids NodeBase
but maintains the same (or similar) interface?
Upvotes: 0
Views: 1783
Reputation: 63019
You don't need NodeBase
nor NodePtr
.
struct Node : std::enable_shared_from_this {
int val;
std::shared_ptr<Node> left, right;
std::weak_ptr<Node> parent;
Node(int v, std::weak_ptr<Node> p) : val(v), left(), right(), parent(p) {}
void add_node_left(int v) {
left = std::make_shared<Node>(v, weak_from_this()); // shared_from_this() pre C++17
}
void add_node_right(int v) {
right = std::make_shared<Node>(v, weak_from_this()); // shared_from_this() pre C++17
}
};
Upvotes: 2