new visitor implementation now running.
Veryfied the tests, cleaned up. TODO: concurrency, error checks and convienience shortcuts.
This commit is contained in:
parent
cb602663d0
commit
9aa3cc11e8
14 changed files with 101 additions and 221 deletions
|
|
@ -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<ToolBase> getTag() = 0;
|
||||
};
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ namespace cinelerra
|
|||
* Mixin for attaching a type tag to the concrete tool implementation
|
||||
*/
|
||||
template<class TOOLImpl, class BASE=Tool<> >
|
||||
class ToolType : public BASE
|
||||
class ToolTag : public BASE
|
||||
{
|
||||
typedef typename BASE::ToolBase ToolBase;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
Buildable - marker interface denoting any MObject able to be treated by Tools
|
||||
|
||||
Copyright (C) CinelerraCV
|
||||
2007, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
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
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
BUILDABLE.hpp - marker interface denoting any (M)Object able to be treated by Tools
|
||||
|
||||
Copyright (C) CinelerraCV
|
||||
2007, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
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
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
BuilderTool - Interface, (visiting) tool for processing MObjects
|
||||
|
||||
Copyright (C) CinelerraCV
|
||||
2007, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
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
|
||||
|
|
@ -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 TOOLImpl>
|
||||
class BuilderToolType
|
||||
: public cinelerra::visitor::ToolType<TOOLImpl, BuilderTool>
|
||||
class BuilderToolTag
|
||||
: public cinelerra::visitor::ToolTag<TOOLImpl, BuilderTool>
|
||||
{ }
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include <list>
|
||||
|
||||
#include "proc/mobject/buildable.hpp"
|
||||
#include "proc/mobject/builder/buildertool.hpp"
|
||||
#include "proc/mobject/session/segment.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#include <tr1/memory>
|
||||
|
||||
#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?
|
||||
|
|
|
|||
|
|
@ -185,15 +185,27 @@ END
|
|||
TEST "VisitingTool_test" VisitingTool_test <<END
|
||||
out: === Babbler meets Boss and BigBoss ===
|
||||
out: Hello Boss, nice to meet you...
|
||||
out: Hello big Boss, nice to meet you...
|
||||
out: Hello Big Boss, nice to meet you...
|
||||
out: === Babbler meets HomoSapiens and Leader ===
|
||||
out: Hello Boss, nice to meet you...
|
||||
out: === Blatherer meets Leader, Visionary and HomoSapiens masqueraded as HomoSapiens ===
|
||||
out: === Blatherer meets Leader and Visionary masqueraded as Chief ===
|
||||
out: Hello we-do-everything-for-YOU, nice to meet you...
|
||||
out: Hello we-do-everything-for-YOU, nice to meet you...
|
||||
out: === VerboseVistr masqueraded as Tool meets Leader and Visionary masqueraded as HomoSapiens ===
|
||||
out: === Blatherer masqueraded as Tool meets Leader and Visionary masqueraded as Leader ===
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "VisitingToolExtended_test" VisitingToolExtended_test <<END
|
||||
out: === Babbler meets Boss and BigBoss ===
|
||||
out: Hello Boss, nice to meet you...
|
||||
out: Hello Big Boss, nice to meet you...
|
||||
out: === Babbler meets HomoSapiens and Leader ===
|
||||
out: Hello Boss, nice to meet you...
|
||||
out: === Blatherer meets Leader and Visionary masqueraded as Chief ===
|
||||
out: we-do-everything-for-YOU!
|
||||
out: Hello Mr.Future, nice to meet you...
|
||||
out: === Babbler masqueraded as Tool meets Leader and Visionary masqueraded as HomoSapiens ===
|
||||
out: Hello Boss, nice to meet you...
|
||||
out: Hello Boss, nice to meet you...
|
||||
out: === Babbler masqueraded as Tool meets Leader and Visionary masqueraded as Leader ===
|
||||
out: Hello Boss, nice to meet you...
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include "common/test/run.hpp"
|
||||
#include "common/visitor.hpp"
|
||||
//#include "common/util.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
|
@ -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<Boss,Babbler>,
|
||||
public Applicable<BigBoss,Babbler>,
|
||||
public ToolType<Babbler, VerboseVisitor<Tool> >
|
||||
public ToolTag<Babbler, VerboseVisitor<Tool> >
|
||||
{
|
||||
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<class RET>
|
||||
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<void, Catched> Hastalavista;
|
||||
typedef Visitable<Hastalavista> 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<Visionary,Blatherer,Hastalavista>,
|
||||
public ToolType<Blatherer, VerboseVisitor<Hastalavista> >
|
||||
public ToolTag<Blatherer, VerboseVisitor<Hastalavista> >
|
||||
{
|
||||
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
|
||||
* <ul><li>calling the correct visiting tool specialized function
|
||||
* for given concrete hierarchy classes</li>
|
||||
* <li>visiting tool not declaring to visit some class</li>
|
||||
* <li>newly added class causes the catch-all to be invoked
|
||||
* when visited by known visitor</li>
|
||||
* </ul>
|
||||
* @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
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include "common/test/run.hpp"
|
||||
#include "common/visitor.hpp"
|
||||
//#include "common/util.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
|
@ -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<Boss,Babbler>,
|
||||
public Applicable<BigBoss,Babbler>,
|
||||
public ToolType<Babbler, VerboseVisitor>
|
||||
public Applicable<Visionary,Babbler>,
|
||||
public ToolTag<Babbler, VerboseVisitor>
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,15 +48,16 @@ namespace mobject
|
|||
public:
|
||||
DummyMO() { };
|
||||
virtual bool isValid() const { return true;}
|
||||
DEFINE_PROCESSABLE_BY (BuilderTool);
|
||||
};
|
||||
|
||||
class TestTool : public BuilderToolType<TestTool>,
|
||||
class TestTool : public BuilderToolTag<TestTool>,
|
||||
public Applicable<Clip,TestTool>,
|
||||
public Applicable<AbstractMO,TestTool>
|
||||
{
|
||||
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"; }
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue