#include #include #include #include template struct TreeTraits { // By ensuring that this is nonsense for TreeKind, we know that this // version of the template can never apply, and a specialization // must be used. using Unresolved = typename TreeKind::UnspecializedTraitError; // must publish // types // node type // value_type // behaviors // get_root // get_children // get_value }; template> bool printGraphviz(const TreeKind& tree) { using node_type = typename Traits::node_type; auto traverse = [&tree] (node_type& node, auto& traverse) -> void { auto children = Traits::get_children(tree, node); auto value = Traits::get_value(node); for (node_type child : children) { auto child_value = Traits::get_value(child); std::cout << " " << value << " -> " << child_value << ";\n"; traverse(child, traverse); } }; std::cout << "digraph {\n"; auto root = Traits::get_root(tree); traverse(root, traverse); std::cout << "}\n"; } template struct TreeTraits> { using tree = std::list; using node_type = typename tree::const_iterator; using value_type = T; static node_type get_root(const tree& t) noexcept { return t.cbegin(); } static std::vector get_children(const tree& t, const node_type& node) noexcept { auto next = node; ++next; if (next == t.end()) { return {}; } else { return std::vector{ next }; } } static value_type get_value(const node_type& node) noexcept { return *node; } }; template struct Node { Element e; Node* left = nullptr; Node* right = nullptr; }; template struct TreeTraits> { using tree = Node; using node_type = const Node*; using value_type = T; static node_type get_root(const tree& t) noexcept { return &t; } static std::vector get_children(const tree& t, const node_type node) noexcept { std::vector children; children.reserve(2); if (node->left) { children.push_back(node->left); } if (node->right) { children.push_back(node->right); } return children; } static value_type get_value(const node_type node) noexcept { return node->e; } }; int main(int argc, const char** argv) { std::list numbers = { 1, 2, 3, 5, 8, 13 }; std::list strings = { "one", "two", "three", "five", "eight", "thirteen" }; printGraphviz(numbers); printGraphviz(strings); // This works not only for other element types, // but for other *tree* kinds as well!! Node a{1}; Node b{2}; Node c{3}; Node d{4}; Node e{5}; a.left = &b; a.right = &c; c.left = &d; c.right = &e; printGraphviz(a); return 0; }