From 613ced9c74ce14644a926868bb02dec27af2321c Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Thu, 31 Jul 2003 00:09:52 +0000 Subject: [PATCH] - print_context::duplicate() wasn't virtual - fixed static initialization order problem with the print_context registry - print methods can use basic::print_dispatch<>() to re-enter the double dispatch mechanism to defer to superclass methods --- ginac/basic.cpp | 16 +++++++++++++++- ginac/basic.h | 16 ++++++++++++++-- ginac/function.pl | 4 ++-- ginac/print.h | 16 ++++++++++------ ginac/registrar.h | 18 +++++++++--------- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/ginac/basic.cpp b/ginac/basic.cpp index 66e6c901..725f28a2 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -124,15 +124,27 @@ void basic::archive(archive_node &n) const * @param level value that is used to identify the precedence or indentation * level for placing parentheses and formatting */ void basic::print(const print_context & c, unsigned level) const +{ + 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 = &get_class_info(); + const registered_class_info * reg_info = &ri; const print_context_class_info * pc_info = &c.get_class_info(); next_class: +std::clog << "searching class " << reg_info->options.get_name() << std::endl; const std::vector & pdt = reg_info->options.get_print_dispatch_table(); next_context: +std::clog << "searching context " << pc_info->options.get_name() << ", ID " << pc_info->options.get_id() << std::endl; unsigned id = pc_info->options.get_id(); if (id >= pdt.size() || !(pdt[id].is_valid())) { @@ -161,6 +173,8 @@ next_context: } else { // Call method +std::clog << "method found, calling" << std::endl; +std::clog << " this = " << class_name() << ", context = " << c.class_name() << std::endl; pdt[id](*this, c, level); } } diff --git a/ginac/basic.h b/ginac/basic.h index 1bd89cac..d50c7ca3 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -192,6 +192,19 @@ protected: // functions that should be called from class ex only // non-virtual functions in this class public: + /** 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 */ + template + void print_dispatch(const print_context & c, unsigned level) const + { + print_dispatch(T::get_class_info_static(), c, level); + } + + void print_dispatch(const registered_class_info & ri, const print_context & c, unsigned level) const; + ex subs_one_level(const exmap & m, unsigned options) const; ex diff(const symbol & s, unsigned nth = 1) const; int compare(const basic & other) const; @@ -209,7 +222,6 @@ public: protected: void ensure_if_modifiable() const; -private: void do_print(const print_context & c, unsigned level) const; void do_print_tree(const print_tree & c, unsigned level) const; void do_print_python_repr(const print_python_repr & c, unsigned level) const; @@ -244,7 +256,7 @@ inline bool is_a(const basic &obj) template inline bool is_exactly_a(const basic &obj) { - return obj.tinfo() == T::reg_info.options.get_id(); + return obj.tinfo() == T::get_class_info_static().options.get_id(); } } // namespace GiNaC diff --git a/ginac/function.pl b/ginac/function.pl index b3183da8..749df21d 100755 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -79,7 +79,7 @@ $print_func_interface=generate( template function_options & print_func(print_funcp_${N} p) { test_and_set_nparams(${N}); - set_print_func(Ctx::reg_info.options.get_id(), print_funcp(p)); + set_print_func(Ctx::get_class_info_static().options.get_id(), print_funcp(p)); return *this; } END_OF_PRINT_FUNC_INTERFACE @@ -274,7 +274,7 @@ $print_func_interface template function_options & print_func(print_funcp_exvector p) { print_use_exvector_args = true; - set_print_func(Ctx::reg_info.options.get_id(), print_funcp(p)); + set_print_func(Ctx::get_class_info_static().options.get_id(), print_funcp(p)); return *this; } diff --git a/ginac/print.h b/ginac/print.h index 6b80d488..dccaecd8 100644 --- a/ginac/print.h +++ b/ginac/print.h @@ -69,19 +69,23 @@ public: \ typedef supername inherited; \ friend class function_options; \ friend class registered_class_options; \ -private: \ - static GiNaC::print_context_class_info reg_info; \ public: \ - virtual const GiNaC::print_context_class_info &get_class_info() const { return reg_info; } \ - virtual const char *class_name() const { return reg_info.options.get_name(); } \ + static const GiNaC::print_context_class_info &get_class_info_static(); \ + virtual const GiNaC::print_context_class_info &get_class_info() const { return classname::get_class_info_static(); } \ + virtual const char *class_name() const { return classname::get_class_info_static().options.get_name(); } \ \ classname(); \ - classname * duplicate() const { return new classname(*this); } \ + virtual classname * duplicate() const { return new classname(*this); } \ private: /** Macro for inclusion in the implementation of each print_context class. */ #define GINAC_IMPLEMENT_PRINT_CONTEXT(classname, supername) \ - GiNaC::print_context_class_info classname::reg_info = GiNaC::print_context_class_info(print_context_options(#classname, #supername, next_print_context_id++)); +const GiNaC::print_context_class_info &classname::get_class_info_static() \ +{ \ + static GiNaC::print_context_class_info reg_info = GiNaC::print_context_class_info(GiNaC::print_context_options(#classname, #supername, GiNaC::next_print_context_id++)); \ + return reg_info; \ +} + extern unsigned next_print_context_id; diff --git a/ginac/registrar.h b/ginac/registrar.h index 9610f6c0..33e54de5 100644 --- a/ginac/registrar.h +++ b/ginac/registrar.h @@ -58,21 +58,21 @@ public: template registered_class_options & print_func(void f(const T &, const C & c, unsigned)) { - set_print_func(Ctx::reg_info.options.get_id(), f); + set_print_func(Ctx::get_class_info_static().options.get_id(), f); return *this; } template registered_class_options & print_func(void (T::*f)(const C &, unsigned)) { - set_print_func(Ctx::reg_info.options.get_id(), f); + set_print_func(Ctx::get_class_info_static().options.get_id(), f); return *this; } template registered_class_options & print_func(const print_functor & f) { - set_print_func(Ctx::reg_info.options.get_id(), f); + set_print_func(Ctx::get_class_info_static().options.get_id(), f); return *this; } @@ -98,12 +98,12 @@ typedef class_info registered_class_info; #define GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(classname, supername) \ public: \ typedef supername inherited; \ - template friend bool is_exactly_a(const GiNaC::basic &obj); \ private: \ static GiNaC::registered_class_info reg_info; \ public: \ - virtual const GiNaC::registered_class_info &get_class_info() const { return reg_info; } \ - virtual const char *class_name() const { return reg_info.options.get_name(); } \ + static const GiNaC::registered_class_info &get_class_info_static() { return reg_info; } \ + virtual const GiNaC::registered_class_info &get_class_info() const { return classname::get_class_info_static(); } \ + virtual const char *class_name() const { return classname::get_class_info_static().options.get_name(); } \ \ classname(const GiNaC::archive_node &n, GiNaC::lst &sym_lst); \ virtual void archive(GiNaC::archive_node &n) const; \ @@ -122,9 +122,9 @@ public: \ GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(classname, supername) \ public: \ classname(); \ - classname * duplicate() const { return new classname(*this); } \ + virtual classname * duplicate() const { return new classname(*this); } \ \ - void accept(GiNaC::visitor & v) const \ + virtual void accept(GiNaC::visitor & v) const \ { \ if (visitor *p = dynamic_cast(&v)) \ p->visit(*this); \ @@ -132,7 +132,7 @@ public: \ inherited::accept(v); \ } \ protected: \ - int compare_same_type(const GiNaC::basic & other) const; \ + virtual int compare_same_type(const GiNaC::basic & other) const; \ private: /** Macro for inclusion in the implementation of each registered class. */ -- 2.44.0