// clang-format off #include #include #include #include #include #include using namespace std; namespace nodes { struct Number; struct Plus; struct Times; struct Node { virtual ~Node() {} virtual auto value() const -> int = 0; virtual auto to_rpn() const -> string = 0; struct Visitor { virtual void accept(const Number& expr) = 0; virtual void accept(const Plus& expr) = 0; virtual void accept(const Times& expr) = 0; }; virtual void visit(Visitor& viz) const = 0; }; struct Number : Node { explicit Number(int value) : val(value) { } auto value() const -> int override { return val; } auto to_rpn() const -> string override { return to_string(val); } void visit(Visitor& viz) const override { viz.accept(*this); } int val; }; struct Plus : Node { Plus(const Node& left, const Node& right) : left(left), right(right) { } auto value() const -> int override { return left.value() + right.value(); } auto to_rpn() const -> string override { return left.to_rpn() + " " + right.to_rpn() + " +"; } void visit(Visitor& viz) const override { viz.accept(*this); } const Node& left; const Node& right; }; struct Times : Node { Times(const Node& left, const Node& right) : left(left), right(right) { } auto value() const -> int override { return left.value() * right.value(); } auto to_rpn() const -> string override { return left.to_rpn() + " " + right.to_rpn() + " &"; } void visit(Visitor& viz) const override { viz.accept(*this); } const Node& left; const Node& right; }; } namespace typeswitch { using namespace nodes; auto to_rpn(const Node& node) -> string { if (auto expr = dynamic_cast(&node)) { return to_string(expr->value()); } else if (auto expr = dynamic_cast(&node)) { return to_rpn(expr->left) + " " + to_rpn(expr->right) + " +"; } else if (auto expr = dynamic_cast(&node)) { return to_rpn(expr->left) + " " + to_rpn(expr->right) + " *"; } throw runtime_error("unknown node type"); } } namespace visitor { using namespace nodes; struct RPNVisitor : Node::Visitor { void accept(const Number& expr) { result = to_string(expr.val); } void accept(const Plus& expr) { expr.left.visit(*this); string l = result; expr.right.visit(*this); result = l + " " + result + " +"; } void accept(const Times& expr) { expr.left.visit(*this); string l = result; expr.right.visit(*this); result = l + " " + result + " *"; } string result; }; auto to_rpn(const Node& node) -> string { RPNVisitor viz; node.visit(viz); return viz.result; } } namespace funtable { using namespace nodes; unordered_map RPNformatters; auto to_rpn(const Node& node) -> string { return RPNformatters[typeid(node)](node); } struct Init { Init() { RPNformatters[typeid(Number)] = [](const Node& node) { return to_string(static_cast(node).val); }; RPNformatters[typeid(Plus)] = [](const Node& node) { auto expr = static_cast(node); return to_rpn(expr.left) + " " + to_rpn(expr.right) + " +"; }; RPNformatters[typeid(Times)] = [](const Node& node) { auto expr = static_cast(node); return to_rpn(expr.left) + " " + to_rpn(expr.right) + " *"; }; } } init; } #include #include #include namespace openmethods { using namespace nodes; using boost::openmethod::virtual_ptr; BOOST_OPENMETHOD_CLASSES(Node, Number, Plus, Times); BOOST_OPENMETHOD(to_rpn, (virtual_ptr), string); BOOST_OPENMETHOD_OVERRIDE(to_rpn, (virtual_ptr expr), string) { return std::to_string(expr->val); } BOOST_OPENMETHOD_OVERRIDE(to_rpn, (virtual_ptr expr), string) { return to_rpn(expr->left) + " " + to_rpn(expr->right) + " +"; } BOOST_OPENMETHOD_OVERRIDE(to_rpn, (virtual_ptr expr), string) { return to_rpn(expr->left) + " " + to_rpn(expr->right) + " *"; } BOOST_OPENMETHOD(value, (virtual_ptr), int); BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr expr), int) { return expr->val; } BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr expr), int) { return value(expr->left) + value(expr->right); } BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr expr), int) { return value(expr->left) * value(expr->right); } } namespace virtual_ptr_demo { using namespace boost::openmethod; using namespace nodes; BOOST_OPENMETHOD(value, (virtual_ptr), int); auto call_via_vptr(virtual_ptr node) -> int { return value(node); } BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr expr), int) { return value(expr->left) + value(expr->right); } auto make_node_ptr(const Node& node) { return virtual_ptr(node); } auto make_final_node_ptr(const Plus& node) { return final_virtual_ptr(node); } } namespace unique_virtual_ptr_demo { using namespace boost::openmethod; struct Number; struct Plus; struct Times; struct Node { virtual ~Node() {} }; struct Number : Node { explicit Number(int value) : val(value) { } int val; }; struct Plus : Node { Plus(unique_virtual_ptr&& left, unique_virtual_ptr&& right) : left(std::move(left)), right(std::move(right)) { } unique_virtual_ptr left, right; }; struct Times : Node { Times(unique_virtual_ptr&& left, unique_virtual_ptr&& right) : left(std::move(left)), right(std::move(right)) { } unique_virtual_ptr left, right; }; BOOST_OPENMETHOD_CLASSES(Node, Number, Plus, Times); BOOST_OPENMETHOD(value, (virtual_ptr), int); BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr expr), int) { return value(expr->left) + value(expr->right); } BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr expr), int) { return expr->val; } BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr expr), int) { return value(expr->left) * value(expr->right); } BOOST_OPENMETHOD(to_rpn, (virtual_ptr), string); BOOST_OPENMETHOD_OVERRIDE(to_rpn, (virtual_ptr expr), string) { return std::to_string(expr->val); } BOOST_OPENMETHOD_OVERRIDE(to_rpn, (virtual_ptr expr), string) { return to_rpn(expr->left) + " " + to_rpn(expr->right) + " +"; } BOOST_OPENMETHOD_OVERRIDE(to_rpn, (virtual_ptr expr), string) { return to_rpn(expr->left) + " " + to_rpn(expr->right) + " *"; } } namespace core_api { using namespace boost::openmethod; using namespace nodes; use_classes use_node_classes; struct value_id; using value = method)->int>; auto number_value(virtual_ptr node) -> int { return node->val; } value::override add_number_value; template auto binary_op(virtual_ptr expr) -> int { return Op()(value::fn(expr->left), value::fn(expr->right)); } BOOST_OPENMETHOD_REGISTER(value::override>>); BOOST_OPENMETHOD_REGISTER(value::override>>); } auto main() -> int { boost::openmethod::initialize(); { using namespace nodes; Number n2(2), n3(3), n4(4); Plus sum(n3, n4); Times product(n2, sum); const Node& expr = product; cout << expr.value() << "\n"; cout << expr.value() << "\n"; cout << typeswitch::to_rpn(expr) << " = " << expr.value() << "\n"; cout << visitor::to_rpn(expr) << " = " << expr.value() << "\n"; cout << funtable::to_rpn(expr) << " = " << expr.value() << "\n"; cout << openmethods::to_rpn(expr) << " = " << expr.value() << "\n"; cout << core_api::value::fn(expr) << "\n"; } { using boost::openmethod::make_unique_virtual; using namespace unique_virtual_ptr_demo; auto expr = make_unique_virtual( make_unique_virtual(2), make_unique_virtual( make_unique_virtual(3), make_unique_virtual(4) )); cout << to_rpn(expr) << " = " << value(expr) << "\n"; } return 0; }