#include #include #include #include /// Port of tree.py to C++ template struct Tree { // FIXME make T not require default constructability struct Node { protected: friend Tree; Node* parent = nullptr; std::vector children{}; T item{}; public: ~Node() { for(auto& child: children) delete child; } T& data() { return item; } const T& data() const { return item; } bool is_leaf() const { return children.size() == 0; } Node* create_leaf(const T& item) { auto* node = new Node; node->parent = this; node->item = item; children.push_back(node); return node; } template void walk(Fn&& fn) { fn(this); if(!is_leaf()) { for(auto& child: children) child->walk(fn); } } template std::optional find_child(Pred&& predicate) { if(predicate(*this)) return this; for(auto& child: children) if(predicate(*child)) return child; return std::nullopt; } std::size_t parent_count() const { auto* parent = this->parent; auto parent_count = 0z; while(parent) { parent_count ++; parent = parent->parent; } return parent_count; } }; Tree() { root = new Node; } ~Tree() { delete root; } // Trees are not copyable but they can move Tree(const Tree&) = delete; Tree(Tree&&) = default; template void walk(Fn&& fn) { root->walk(fn); } Node* create_leaf(const T& item) { return root->create_leaf(item); } private: Node* root; }; void test_tree() { Tree tree; auto* virus = tree.create_leaf("Virus"); auto* worm = tree.create_leaf("Worm"); auto* test = virus->create_leaf("test"); test->create_leaf("a"); test->create_leaf("b"); test->create_leaf("c"); test->create_leaf("884"); tree.walk([](auto* node) { auto tab_count = node->parent_count(); auto& data = node->data(); for(auto i = 0; i < tab_count; ++i) std::printf("\t"); if(data.empty()) { std::printf("(root)\n"); } else { std::printf("%s\n", data.c_str()); } }); } int main() { test_tree(); return 0; }