From 9aa3cc11e8b106c0dafe279092a693cd22d01aa4 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 5 Jan 2008 14:26:28 +0100 Subject: [PATCH] new visitor implementation now running. Veryfied the tests, cleaned up. TODO: concurrency, error checks and convienience shortcuts. --- src/common/visitor.hpp | 4 +- src/proc/mobject/buildable.cpp | 43 --------- src/proc/mobject/buildable.hpp | 43 --------- src/proc/mobject/builder/buildertool.cpp | 40 --------- src/proc/mobject/builder/buildertool.hpp | 6 +- src/proc/mobject/builder/nodecreatertool.cpp | 1 - src/proc/mobject/builder/nodecreatertool.hpp | 1 - src/proc/mobject/builder/segmentationtool.cpp | 1 - src/proc/mobject/builder/segmentationtool.hpp | 1 - src/proc/mobject/mobject.hpp | 1 - tests/50components.tests | 26 ++++-- .../common/visitingtoolextendedtest.cpp | 87 ++++++++++--------- tests/components/common/visitingtooltest.cpp | 63 +++++++------- .../proc/mobject/builder/buildertooltest.cpp | 5 +- 14 files changed, 101 insertions(+), 221 deletions(-) delete mode 100644 src/proc/mobject/buildable.cpp delete mode 100644 src/proc/mobject/buildable.hpp delete mode 100644 src/proc/mobject/builder/buildertool.cpp diff --git a/src/common/visitor.hpp b/src/common/visitor.hpp index 8509c4fc0..20dfabaeb 100644 --- a/src/common/visitor.hpp +++ b/src/common/visitor.hpp @@ -101,7 +101,7 @@ namespace cinelerra virtual ~Tool () { }; ///< use RTTI for all visiting tools /** allows discovery of the concrete Tool type when dispatching a - * visitor call. Can be implemented by inheriting from ToolType */ + * visitor call. Can be implemented by inheriting from ToolTag */ virtual Tag getTag() = 0; }; @@ -110,7 +110,7 @@ namespace cinelerra * Mixin for attaching a type tag to the concrete tool implementation */ template > - class ToolType : public BASE + class ToolTag : public BASE { typedef typename BASE::ToolBase ToolBase; diff --git a/src/proc/mobject/buildable.cpp b/src/proc/mobject/buildable.cpp deleted file mode 100644 index de1e87cbd..000000000 --- a/src/proc/mobject/buildable.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - Buildable - marker interface denoting any MObject able to be treated by Tools - - Copyright (C) CinelerraCV - 2007, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -* *****************************************************/ - - -#include "proc/mobject/buildable.hpp" -#include "proc/mobject/builder/buildertool.hpp" - -namespace mobject - { - - - /** typically the provided actual Tool class will - * contain overloaded fuctions for treating - * different Buildable subclasses specifically - */ -/* Buildable::ReturnType - Buildable::apply (builder::BuilderTool& tool) - { - return dispatchOp (*this, tool); - } -*/ - - -} // namespace mobject diff --git a/src/proc/mobject/buildable.hpp b/src/proc/mobject/buildable.hpp deleted file mode 100644 index 09de1d953..000000000 --- a/src/proc/mobject/buildable.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - BUILDABLE.hpp - marker interface denoting any (M)Object able to be treated by Tools - - Copyright (C) CinelerraCV - 2007, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - - -#ifndef MOBJECT_BUILDABLE_H -#define MOBJECT_BUILDABLE_H - - -#include "common/visitor.hpp" -#include "proc/mobject/builder/buildertool.hpp" - - - -namespace mobject - { - using cinelerra::visitor::Visitable; - - - - - - -} // namespace mobject -#endif diff --git a/src/proc/mobject/builder/buildertool.cpp b/src/proc/mobject/builder/buildertool.cpp deleted file mode 100644 index a5d91c6b0..000000000 --- a/src/proc/mobject/builder/buildertool.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - BuilderTool - Interface, (visiting) tool for processing MObjects - - Copyright (C) CinelerraCV - 2007, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -* *****************************************************/ - - -#include "proc/mobject/builder/buildertool.hpp" - - -namespace mobject - { - namespace builder - { - - - - /** */ - - - - } // namespace mobject::builder - -} // namespace mobject diff --git a/src/proc/mobject/builder/buildertool.hpp b/src/proc/mobject/builder/buildertool.hpp index fb472cd05..883359c5c 100644 --- a/src/proc/mobject/builder/buildertool.hpp +++ b/src/proc/mobject/builder/buildertool.hpp @@ -56,7 +56,7 @@ namespace mobject * each Tool contains the concrete implementation for one task to be done * to the various MObject classes. The concrete builder tool implementation * should not diretcly inherit from this base interface, but rather through - * an instantiation of the BuilderToolType template. Additionally, it should + * an instantiation of the BuilderToolTag template. Additionally, it should * inherit from the Applicable template parametrized with all conctrete * Buildable classes, for which it wants calls to be dispatched. */ @@ -64,8 +64,8 @@ namespace mobject template - class BuilderToolType - : public cinelerra::visitor::ToolType + class BuilderToolTag + : public cinelerra::visitor::ToolTag { } ; diff --git a/src/proc/mobject/builder/nodecreatertool.cpp b/src/proc/mobject/builder/nodecreatertool.cpp index adecc6ebd..d4e0d78dd 100644 --- a/src/proc/mobject/builder/nodecreatertool.cpp +++ b/src/proc/mobject/builder/nodecreatertool.cpp @@ -22,7 +22,6 @@ #include "proc/mobject/builder/nodecreatertool.hpp" -#include "proc/mobject/buildable.hpp" #include "proc/mobject/session/clip.hpp" #include "proc/mobject/session/effect.hpp" #include "proc/mobject/session/auto.hpp" diff --git a/src/proc/mobject/builder/nodecreatertool.hpp b/src/proc/mobject/builder/nodecreatertool.hpp index 59e5cc831..6eebc98c4 100644 --- a/src/proc/mobject/builder/nodecreatertool.hpp +++ b/src/proc/mobject/builder/nodecreatertool.hpp @@ -25,7 +25,6 @@ #define MOBJECT_BUILDER_NODECREATERTOOL_H #include "proc/mobject/builder/buildertool.hpp" -#include "proc/mobject/buildable.hpp" #include "proc/engine/processor.hpp" diff --git a/src/proc/mobject/builder/segmentationtool.cpp b/src/proc/mobject/builder/segmentationtool.cpp index 0ede72ecd..a98a63f83 100644 --- a/src/proc/mobject/builder/segmentationtool.cpp +++ b/src/proc/mobject/builder/segmentationtool.cpp @@ -22,7 +22,6 @@ #include "proc/mobject/builder/segmentationtool.hpp" -#include "proc/mobject/buildable.hpp" #include "proc/mobject/session/clip.hpp" #include "proc/mobject/session/effect.hpp" #include "proc/mobject/session/segment.hpp" diff --git a/src/proc/mobject/builder/segmentationtool.hpp b/src/proc/mobject/builder/segmentationtool.hpp index 7ed4f65f2..f913836ca 100644 --- a/src/proc/mobject/builder/segmentationtool.hpp +++ b/src/proc/mobject/builder/segmentationtool.hpp @@ -26,7 +26,6 @@ #include -#include "proc/mobject/buildable.hpp" #include "proc/mobject/builder/buildertool.hpp" #include "proc/mobject/session/segment.hpp" diff --git a/src/proc/mobject/mobject.hpp b/src/proc/mobject/mobject.hpp index 08fda383d..b051a49ec 100644 --- a/src/proc/mobject/mobject.hpp +++ b/src/proc/mobject/mobject.hpp @@ -28,7 +28,6 @@ #include #include "cinelerra.h" -#include "proc/mobject/buildable.hpp" #include "proc/mobject/builder/buildertool.hpp" #include "proc/mobject/placement.hpp" #include "proc/asset.hpp" // TODO finally not needed? diff --git a/tests/50components.tests b/tests/50components.tests index 0e71172d0..88434f3b2 100644 --- a/tests/50components.tests +++ b/tests/50components.tests @@ -185,15 +185,27 @@ END TEST "VisitingTool_test" VisitingTool_test < #include @@ -37,7 +36,7 @@ namespace cinelerra { namespace visitor { - namespace test + namespace test2 { typedef visitor::Tool<> Tool; @@ -74,7 +73,7 @@ namespace cinelerra class Babbler : public Applicable, public Applicable, - public ToolType > + public ToolTag > { public: void treat (Boss&) { talk_to("Boss"); } @@ -82,53 +81,63 @@ namespace cinelerra }; // the classes above comprise the standard use case, - // what follows are rather exotic corner cases - + // what follows covers rather exotic corner cases + + + /** defines an catch-all-function instead of the silent default error handler */ template struct Catched { - RET onUnknown (HomoSapiens&) { cout << "we-do-everything-for-YOU!\n"; } ///< catch-all function + RET onUnknown (HomoSapiens&) { cout << "we-do-everything-for-YOU!\n"; } }; + /** defines another different visiting tool base */ typedef visitor::Tool Hastalavista; typedef Visitable Chief; ///< another special kind of visitables + +#define DEFINE_HASTALAVISTA_PROCESSABLE \ + virtual void apply (Hastalavista& tool) \ + { return Chief::dispatchOp (*this, tool); } + /** now mixing the two hierarchies... */ class Leader : public Chief, public Boss ///< can act as HomoSapiens or as Chief { public: using HomoSapiens::apply; - virtual void apply (Hastalavista& tool) { return Chief::dispatchOp (*this, tool); } - }; - - class Visionary : public Leader - { + DEFINE_HASTALAVISTA_PROCESSABLE; }; + class Visionary : public Leader + { + DEFINE_HASTALAVISTA_PROCESSABLE; + }; + + /** Hastalavista-Visiting-Tool + * tailored for the Chief hierarchy + */ class Blatherer : public Applicable, - public ToolType > + public ToolTag > { public: void treat (Leader&) { talk_to("Mr.Future"); } }; - - - + + + + /************************************************************************* - * @test our lib implementation of the acyclic visitor pattern. - * Defines a hierarchy of test classes to check the following cases - *
  • calling the correct visiting tool specialized function - * for given concrete hierarchy classes
  • - *
  • visiting tool not declaring to visit some class
  • - *
  • newly added class causes the catch-all to be invoked - * when visited by known visitor
  • - *
+ * @test more esoteric corner cases of our visitor lib implementation. + * Defines a hierarchy of test classes, which mix two different + * kinds of "visitable" by two disjoint tool base classes. One + * of these base classes uses an explicit error handling + * catch-all-function. */ class VisitingToolExtended_test : public Test { @@ -136,7 +145,7 @@ namespace cinelerra { known_visitor_known_class(); visitor_not_visiting_some_class(); - visitor_treating_new_subclass(); + visiting_mixed_hierarchy(); } void known_visitor_known_class() @@ -168,11 +177,10 @@ namespace cinelerra homo2.apply (bab); // treats Leader as Boss } - void visitor_treating_new_subclass() + void visiting_mixed_hierarchy() { Leader x1; Visionary x2; - HomoSapiens x3; HomoSapiens& homo1 (x1); HomoSapiens& homo2 (x2); @@ -182,26 +190,21 @@ namespace cinelerra Leader& lead2 (x2); Blatherer bla; + cout << "=== Blatherer meets Leader and Visionary masqueraded as Chief ===\n"; + chief1.apply (bla); // catch-all, because Blatherer doesn't declare to be applicalbe to Leader + chief2.apply (bla); // treat(Visionary&) resolved to treat(Leader&) as expected + Babbler bab; Tool& tool1 (bab); - Hastalavista& tool2 (bla); - cout << "=== Blatherer meets Leader and Visionary masqueraded as Chief ===\n"; - chief1.apply (bla); // but now, acting in the Chief hierarchy, the catch-all is called - chief2.apply (bla); cout << "=== Babbler masqueraded as Tool meets Leader and Visionary masqueraded as HomoSapiens ===\n"; - homo1.apply (tool1); // because acting in the HomoSapiens hierarchy, no visiting happens and no catch-all - homo2.apply (tool1); - cout << "=== Blatherer masqueraded as Hastalavista meets Leader and Visionary masqueraded as Leader ===\n"; - lead1.apply (tool2); // nothing happens, because Leader here is treated by his HomoSapiens base - lead2.apply (tool2); - - // note: the following doesn't compile (an this is a feature, not a bug): + homo1.apply (tool1); // because just going through the VTable, the dispatch works as expected + homo2.apply (tool1); // same here (in both cases, the call is resolved to treat(Boss&) as expected) - // "chief1.apply (tool2)" : because the "Chief"-hierarchy enforces the catch-all function - // and the compiler doesn't know Blatherer actually implements this - // catch-all-function, because of the masqueradeing as Tool. Note - // further: the catch-all function can have a more general type - // (in this case HomoSapiens instead of Chief) + cout << "=== Babbler masqueraded as Tool meets Leader and Visionary masqueraded as Leader ===\n"; + lead1.apply (tool1); // nothing happens, because Leader here is treated by his HomoSapiens base + lead2.apply (tool1); // surprisingly the VTable mechanism is choosen here, resulting in an correct dispatch + + // note: the following doesn't compile (an this is a feature, not a bug): // "Chief chief" : is abstract, because the Visitable-Template enforces implementing // the "apply(TOOL&)" function, either directly or via the diff --git a/tests/components/common/visitingtooltest.cpp b/tests/components/common/visitingtooltest.cpp index db9f91588..60dea10af 100644 --- a/tests/components/common/visitingtooltest.cpp +++ b/tests/components/common/visitingtooltest.cpp @@ -23,7 +23,6 @@ #include "common/test/run.hpp" #include "common/visitor.hpp" -//#include "common/util.hpp" #include #include @@ -37,21 +36,10 @@ namespace cinelerra { namespace visitor { - namespace test + namespace test1 { typedef visitor::Tool<> VisitingTool; - class VerboseVisitor - : public VisitingTool - { - protected: - void talk_to (string guy) - { - cout << format ("Hello %s, nice to meet you...\n") % guy; - } - }; - - class HomoSapiens : public Visitable<> { public: @@ -64,40 +52,47 @@ namespace cinelerra DEFINE_PROCESSABLE_BY (VisitingTool); }; - // the classes above comprise the standard visitor use case, - // now we'll extend the hierarchy a bit... - - class BigBoss : public Boss { public: - DEFINE_PROCESSABLE_BY (VerboseVisitor); + DEFINE_PROCESSABLE_BY (VisitingTool); + }; + + class Visionary : public Boss + { + DEFINE_PROCESSABLE_BY (VisitingTool); + }; + + class Leader : public Visionary + { }; + + + class VerboseVisitor + : public VisitingTool + { + protected: + void talk_to (string guy) + { + cout << format ("Hello %s, nice to meet you...\n") % guy; + } + }; class Babbler : public Applicable, public Applicable, - public ToolType + public Applicable, + public ToolTag { public: void treat (Boss&) { talk_to("Boss"); } void treat (BigBoss&) { talk_to("Big Boss"); } }; - - - class Leader : public Boss - { - }; - - class Visionary : public Leader - { - }; // note the following details: // - Babbler "forgot" to declare being applicable to HomoSapiens - // - BigBoss accepts only the subclass (VerboseVisitor) - // - we have new derived classes without separate "apply()"-implementation + // - we have new derived class Leader without separate "apply()"-implementation @@ -140,16 +135,16 @@ namespace cinelerra void visiting_extended_hierarchy() { HomoSapiens x1; - Visionary x2; + Leader x2; HomoSapiens& homo1 (x1); HomoSapiens& homo2 (x2); - cout << "=== Babbler meets HomoSapiens and Visionary ===\n"; + cout << "=== Babbler meets HomoSapiens and Leader ===\n"; Babbler bab; VisitingTool& vista (bab); - homo1.apply (vista); // error handler (not Applicable to HomoSapiens) - homo2.apply (vista); // treats Visionary as Boss + homo1.apply (vista); // silent error handler (not Applicable to HomoSapiens) + homo2.apply (vista); // Leader handeld as Visionary and treated as Boss } }; diff --git a/tests/components/proc/mobject/builder/buildertooltest.cpp b/tests/components/proc/mobject/builder/buildertooltest.cpp index 9b55b47e6..38c4d6082 100644 --- a/tests/components/proc/mobject/builder/buildertooltest.cpp +++ b/tests/components/proc/mobject/builder/buildertooltest.cpp @@ -48,15 +48,16 @@ namespace mobject public: DummyMO() { }; virtual bool isValid() const { return true;} + DEFINE_PROCESSABLE_BY (BuilderTool); }; - class TestTool : public BuilderToolType, + class TestTool : public BuilderToolTag, public Applicable, public Applicable { public: void treat (Clip& c) { cout << "media is: "<< str(c.getMedia()) <<"\n"; } - void treat (AbstractMO&){ cout << "catch-all-MO.\n"; } + void treat (AbstractMO&){ cout << "unspecific MO.\n"; } void onUnknown (Buildable&){ cout << "catch-all-function called.\n"; } };