- print_context::duplicate() wasn't virtual
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Thu, 31 Jul 2003 00:09:52 +0000 (00:09 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Thu, 31 Jul 2003 00:09:52 +0000 (00:09 +0000)
- 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
ginac/basic.h
ginac/function.pl
ginac/print.h
ginac/registrar.h

index 66e6c90..725f28a 100644 (file)
@@ -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<print_functor> & 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);
        }
 }
index 1bd89ca..d50c7ca 100644 (file)
@@ -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 <class T>
+       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 <class T>
 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
index b3183da..749df21 100755 (executable)
@@ -79,7 +79,7 @@ $print_func_interface=generate(
     template <class Ctx> 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 <class Ctx> 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;
        }
 
index 6b80d48..dccaecd 100644 (file)
@@ -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;
 
index 9610f6c..33e54de 100644 (file)
@@ -58,21 +58,21 @@ public:
        template <class Ctx, class T, class C>
        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 <class Ctx, class T, class C>
        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 <class Ctx>
        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_options> registered_class_info;
 #define GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(classname, supername) \
 public: \
        typedef supername inherited; \
-       template <class isexaclass> 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<visitor *>(&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. */