+ print_dispatch(get_class_info(), c, level);
+}
+
+/** Like print(), but dispatch to the specified class. Can be used by
+ * implementations of print methods to dispatch to the method of the
+ * superclass.
+ *
+ * @see basic::print */
+void basic::print_dispatch(const registered_class_info & ri, const print_context & c, unsigned level) const
+{
+ // Double dispatch on object type and print_context type
+ const registered_class_info * reg_info = &ri;
+ const print_context_class_info * pc_info = &c.get_class_info();
+
+next_class:
+ const std::vector<print_functor> & pdt = reg_info->options.get_print_dispatch_table();
+
+next_context:
+ unsigned id = pc_info->options.get_id();
+ if (id >= pdt.size() || !(pdt[id].is_valid())) {
+
+ // Method not found, try parent print_context class
+ const print_context_class_info * parent_pc_info = pc_info->get_parent();
+ if (parent_pc_info) {
+ pc_info = parent_pc_info;
+ goto next_context;
+ }
+
+ // Method still not found, try parent class
+ const registered_class_info * parent_reg_info = reg_info->get_parent();
+ if (parent_reg_info) {
+ reg_info = parent_reg_info;
+ pc_info = &c.get_class_info();
+ goto next_class;
+ }
+
+ // Method still not found. This shouldn't happen because basic (the
+ // base class of the algebraic hierarchy) registers a method for
+ // print_context (the base class of the print context hierarchy),
+ // so if we end up here, there's something wrong with the class
+ // registry.
+ throw (std::runtime_error(std::string("basic::print(): method for ") + class_name() + "/" + c.class_name() + " not found"));
+
+ } else {
+
+ // Call method
+ pdt[id](*this, c, level);
+ }
+}