diff --git a/src/lib/iter-adapter.hpp b/src/lib/iter-adapter.hpp index d5e2bfbc7..1f668f446 100644 --- a/src/lib/iter-adapter.hpp +++ b/src/lib/iter-adapter.hpp @@ -118,8 +118,8 @@ namespace lib { /** * Adapter for building an implementation of the lumiera forward iterator concept. - * The "current position" is represented as an opaque element (usually an nested iterator), - * with callbacks to the controlling container instance for managing this position. + * The "current position" is represented as an opaque element (usually a nested iterator), + * with callbacks into the controlling container instance to manage this position. * This allows to influence and customise the iteration process to a large extent. * Basically such an IterAdapter behaves like the similar concept from STL, but * - it is not just a disguised pointer (meaning, it's more expensive) @@ -262,10 +262,10 @@ namespace lib { /** * Another Lumiera Forward Iterator building block, based on incorporating a state type - * right into the iterator. Contrast this to IterAdapter referring to an controlling + * right into the iterator. Contrast this to IterAdapter, which refers to a managing * container behind the scenes. Here, all of the state is assumed to live in the * custom type embedded into this iterator, accessed and manipulated through - * a set of free function to be resolved by ADL. + * a set of free functions, picked up through ADL. * * \par Assumptions when building iterators based on IterStateWrapper * There is a custom state representation type ST. @@ -273,7 +273,7 @@ namespace lib { * - this default state represents the \em bottom (invalid) state. * - copyable, because iterators are passed by value * - this type needs to provide an iteration control API through free functions - * -# \c checkPoint establishes, if the given state element represents a valid state + * -# \c checkPoint establishes if the given state element represents a valid state * -# \c iterNext evolves this state by one step (sideeffect) * -# \c yield realises the given state, yielding an element of result type T * diff --git a/src/lib/time/control.hpp b/src/lib/time/control.hpp index f7f78e4d1..9c01c13e6 100644 --- a/src/lib/time/control.hpp +++ b/src/lib/time/control.hpp @@ -50,14 +50,14 @@ ** Thus an interface might accept a time::Control element \em reference (e.g. the ** lumiera::Play::Controller uses this pattern) -- meaning that the client owns the ** Control element and might attach listeners, while the implementation (server side) - ** will attach the Control to mutate an time value entity otherwise not disclosed + ** will attach the Control to mutate a time value entity otherwise not disclosed ** (e.g. the playhead position of the playback process). Of course, in this case ** the client is responsible for keeping the Control element and all listeners ** alive, and to invoke Control#disconnect prior to destroying the element. ** ** Of course, the reversed usage situation would be possible as well: an interface - ** exposing a time::Control, thus allowing to attach target and listeners, while the - ** actual changes will originate somewhere within the service implementation. + ** may expose a time::Control, thus allowing to attach target and listeners, while the + ** actual changes will originate somewhere within the opaque service implementation. ** ** Another usage pattern would be to expose a time::Control \c const&, allowing only to ** impose changes, but not to change the target or listener attachments. To the contrary, diff --git a/src/lib/util-foreach.hpp b/src/lib/util-foreach.hpp index 37f72ed2e..27182b8e3 100644 --- a/src/lib/util-foreach.hpp +++ b/src/lib/util-foreach.hpp @@ -104,9 +104,13 @@ namespace util { /* === specialisations for STL containers and Lumiera Forward Iterators === */ - /** operating on all elements of a STL container. + /** operate on all elements of a STL container. * @note the container is taken by \c const& and * the \c const is \em stripped before iteration. + * @todo reconsider if using rvalue references covers + * the "inline iteration" use case sufficiently, + * so that we can get rid of the unwrapping and + * thus get back to strict const correctness. * @note this case is the default and kicks in * \em unless we detect a Lumiera iterator. * The handling is different for \c and_all @@ -126,7 +130,7 @@ namespace util { } - /** operating on a Lumiera Forward Iterator until exhaustion. */ + /** operate on a Lumiera Forward Iterator until exhaustion. */ template diff --git a/tests/51-gui-model.tests b/tests/51-gui-model.tests index 212a0ca6a..b7218bff3 100644 --- a/tests/51-gui-model.tests +++ b/tests/51-gui-model.tests @@ -6,6 +6,11 @@ TEST "Self-check: testing GUI backbone parts" TestGui_test < @@ -21,12 +21,12 @@ * *****************************************************/ -/** @file visitingtoolconept.cpp - ** While laying the foundations for Session and Builder, Ichthyo came across +/** @file visitingtool-conept.cpp + ** While laying the foundations for Session and Builder, Ichthyo came across ** the necessity to create a custom implementation of the Visitor Pattern - ** optimally suited for Lumiera's needs. This implementation file was - ** used for the draft and is self-contained. The final solution was then - ** extracted as library implementation to visitor.hpp + ** optimally suited for Lumiera's needs. This implementation file was used + ** for the drafting process and is self-contained. The final solution was + ** then extracted later as library implementation into visitor.hpp ** ** Basic considerations ** - ** + ** ** @see visitor.hpp the final lib implementation ** @see visitingtooltest.cpp test cases using our lib implementation ** @see BuilderTool one especially important instantiation @@ -71,7 +71,7 @@ namespace lumiera { // ================================================================== Library ==== - + template class Tag; @@ -111,10 +111,10 @@ namespace lumiera { /** storage for the Tag registry for each concrete tool */ template Tag TagTypeRegistry::tag; - + template size_t Tag::lastRegisteredID (0); - + @@ -128,25 +128,27 @@ namespace lumiera { typedef RET ReturnType; typedef Tool ToolBase; ///< for templating the Tag and Dispatcher - virtual ~Tool () { }; ///< use RTTI for all visiting tools + 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 */ - virtual Tag getTag() = 0; + virtual Tag getTag() =0; }; /** Mixin for attaching a type tag to the concrete tool implementation */ - template > - class ToolType : public BASE + template> + class ToolType + : public BASE { typedef typename BASE::ToolBase ToolBase; public: - virtual Tag getTag() + virtual Tag + getTag() { - TOOLImpl* typeref = 0; - return Tag::get (typeref); + TOOLImpl* typeKey = 0; + return Tag::get (typeKey); } }; @@ -154,9 +156,9 @@ namespace lumiera { /** - * For each posible call entry point via some subclass of the visitable hierarchy, + * For each possible call entry point via some subclass of the visitable hierarchy, * we maintain a dispatcher table to keep track of all concrete tool implementations - * able to recieve and process calls on objects of this subclass. + * able to receive and process calls on objects of this subclass. */ template class Dispatcher @@ -164,7 +166,7 @@ namespace lumiera { typedef typename TOOL::ReturnType ReturnType; /** generator for Trampoline functions, - * used to dispatch calls down to the + * used to dispatch calls down to the * right "treat"-Function on the correct * concrete tool implementation class */ @@ -173,7 +175,7 @@ namespace lumiera { callTrampoline (TAR& obj, TOOL& tool) { // cast down to real implementation type - CHECK (INSTANCEOF (TOOLImpl, &tool)); + CHECK (INSTANCEOF (TOOLImpl, &tool)); TOOLImpl& toolObj = static_cast (tool); // trigger (compile time) overload resolution @@ -183,19 +185,19 @@ namespace lumiera { } typedef ReturnType (*Trampoline) (TAR&, TOOL& ); - - /** VTable for storing the Trampoline pointers */ + + /** custom VTable for storing the Trampoline pointers */ std::vector table_; inline bool is_known (size_t id) { - return id<=table_.size() && table_[id-1]; + return id<=table_.size() && table_[id-1]; } - inline void + inline void storePtr (size_t id, Trampoline func) { // lacks error- and concurrency handling.... @@ -204,7 +206,7 @@ namespace lumiera { table_[id-1] = func; } - inline Trampoline + inline Trampoline storedTrampoline (size_t id) { if (id<=table_.size() && table_[id-1]) @@ -218,12 +220,12 @@ namespace lumiera { { cout << "Error Handler: unregistered combination of (Tool, TargetObject) invoked!\n"; } - + public: - static lib::Depend > instance; + static lib::Depend> instance; - inline ReturnType + inline ReturnType forwardCall (TAR& target, TOOL& tool) { // get concrete type via tool's VTable @@ -232,10 +234,10 @@ namespace lumiera { } template - inline void - enrol(TOOLImpl* typeref) + inline void + enrol (TOOLImpl* typeKey) { - Tag& index = Tag::get (typeref); + Tag& index = Tag::get (typeKey); if (is_known (index)) return; else @@ -246,18 +248,18 @@ namespace lumiera { } }; - + /** storage for the dispatcher table(s) */ template lib::Depend > Dispatcher::instance; - + /** - * concrete visiting tool implementation has to inherit from this - * class for each kind of calls it wants to get dispatched, + * any concrete visiting tool implementation has to inherit from + * this class for each kind of calls it wants to get dispatched, * Allowing us to record the type information. */ template > @@ -267,10 +269,10 @@ namespace lumiera { typedef typename BASE::ToolBase ToolBase; protected: - Applicable () + Applicable() { - TOOLImpl* typeref = 0; - Dispatcher::instance().enrol (typeref); + TOOLImpl* typeKey = 0; + Dispatcher::instance().enrol (typeKey); } virtual ~Applicable () {} @@ -289,19 +291,19 @@ namespace lumiera { /** Marker interface "visitable object". */ template - < class TOOL = Tool + < class TOOL = Tool > class Visitable { protected: - virtual ~Visitable () { }; + virtual ~Visitable() { }; /// @note may differ from TOOL typedef typename TOOL::ToolBase ToolBase; typedef typename TOOL::ReturnType ReturnType; /** @internal used by the DEFINE_PROCESSABLE_BY macro. - * Dispatches to the actual operation on the + * Dispatches to the actual operation on the * "visiting tool" (visitor implementation) * Note: creates a context templated on concrete TAR. */ @@ -329,16 +331,15 @@ namespace lumiera { // =============================================================(End) Library ==== - - namespace test - { - + + namespace test { + typedef Tool VisitingTool; - + class HomoSapiens : public Visitable<> { public: @@ -356,7 +357,7 @@ namespace lumiera { public: DEFINE_PROCESSABLE_BY (VisitingTool); }; - + class Leader : public Boss { }; @@ -364,7 +365,7 @@ namespace lumiera { class Visionary : public Leader { }; - + class VerboseVisitor : public VisitingTool @@ -375,8 +376,8 @@ namespace lumiera { cout << format ("Hello %s, nice to meet you...\n") % guy; } }; - - + + class Babbler : public Applicable, public Applicable, @@ -388,10 +389,10 @@ namespace lumiera { void treat (BigBoss&) { talk_to("Big Boss"); } }; - - - - + + + + @@ -408,11 +409,11 @@ namespace lumiera { */ class VisitingTool_concept : public Test { - virtual void run(Arg) + virtual void run(Arg) { known_visitor_known_class(); visitor_not_visiting_some_class(); - } + } void known_visitor_known_class() { @@ -453,8 +454,4 @@ namespace lumiera { - } // namespace test - - } // namespace visitor_concept_draft - -} // namespace lumiera +}}} // namespace lumiera::visitor_concept_draft::test diff --git a/tests/basics/visitingtoolextendedtest.cpp b/tests/basics/visitingtool-extended-test.cpp similarity index 100% rename from tests/basics/visitingtoolextendedtest.cpp rename to tests/basics/visitingtool-extended-test.cpp diff --git a/tests/basics/visitingtooltest.cpp b/tests/basics/visitingtool-test.cpp similarity index 100% rename from tests/basics/visitingtooltest.cpp rename to tests/basics/visitingtool-test.cpp diff --git a/tests/gui/session-structure-mapping-test.cpp b/tests/gui/session-structure-mapping-test.cpp index 1f73873e1..adea30d79 100644 --- a/tests/gui/session-structure-mapping-test.cpp +++ b/tests/gui/session-structure-mapping-test.cpp @@ -100,6 +100,7 @@ namespace test { void retrieveSessionStructure () { + } }; diff --git a/tests/library/util-foreach-test.cpp b/tests/library/util-foreach-test.cpp index 66e420f69..5993ca209 100644 --- a/tests/library/util-foreach-test.cpp +++ b/tests/library/util-foreach-test.cpp @@ -1,5 +1,5 @@ /* - UtilForeach(Test) - helpers for doing something for each element + UtilForeach(Test) - helpers to perform something for each element Copyright (C) Lumiera.org 2009, Hermann Vosseler diff --git a/tests/library/verb-function-dispatch-test.cpp b/tests/library/verb-function-dispatch-test.cpp new file mode 100644 index 000000000..0ec5c1603 --- /dev/null +++ b/tests/library/verb-function-dispatch-test.cpp @@ -0,0 +1,171 @@ +/* + VerbFunctionDispatch(Test) - Concept to dispatch according to the verbs of a DSL + + Copyright (C) Lumiera.org + 2014, 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 "lib/test/run.hpp" +//#include "lib/util.hpp" +#include "lib/format-string.hpp" + + +//#include +//#include +#include +//#include + +//using boost::lexical_cast; +//using util::contains; +using std::string; +using util::_Fmt; +//using std::cout; +//using std::endl; + + +namespace lib { +namespace test{ + + namespace { + const string BEGINNING("silence"); + } + /** + * a receiver of verb-tokens, + * which renders them verbosely + */ + class VerboseRenderer + : public Receiver + { + string woof() { return "Woof-Woof!"; } + string honk() { return "Honk-Honk!"; } + string moo() { return "Moo-Moo!"; } + string meh() { return "Meh!"; } + }; + + + /** + * Statefull receiver of verb-tokens. + */ + class RecollectingReceiver + : public Receiver + { + string verb_; + _Fmt fmt_; + + string + buildResultTerm (string nextToken) + { + string resultExpression (fmt_ % verb_ % nextToken); + verb_ = nextToken; + return resultExpression; + } + + + string woof() { return buildResultTerm (WOOF); } + string honk() { return buildResultTerm (HONK); } + string moo() { return buildResultTerm (MOO); } + string meh() { return buildResultTerm (MEH); } + + + public: + RecollectingReceiver() + : verb_(BEGINNING) + , fmt_("%s followed by %s") + { } + }; + + + + + + + /***********************************************************************//** + * @test Demonstration/Concept: dispatch a specific function + * based on the given verbs of an embedded custom language. + * - weakness of + * + * @see HashIndexed_test + * @see + */ + class VerbFunctionDispatch_test : public Test + { + + virtual void + run (Arg) + { + VerbSeq tokens = build_test_feed(); + render_verbose (tokens); + verify_dispatch (tokens); + } + + + /** prepare a sequence of verbs + * for the actual tests to work on */ + VerbSeq + build_test_feed() + { + return { + WOOF, + HONK, + MOO, + MEH + }; + } + + + /** @test demonstrate the dispatching + * based on the concrete verb token. + * Here the implementation just prints + * the name of the invoked verb + */ + void + render_verbose (VerbSeq tokens) + { + VerboseRenderer receiver; + for (Verb verb : tokens) + cout << "consuming " << string(verb) + << " -> '" + << verb.applyTo(receiver) + << "'\n"; + } + + + /** @test verify the correct individual dispatch + * through a computation specific for the given verb + */ + void + verify_dispatch (VerbSeq tokens) + { + RecollectingReceiver receiver; + string previous = BEGINNING; + for (Verb verb : tokens) + { + CHECK (previous+" followed by "+string(verb) == verb.applyTo(receiver)); + previous = string(verb); + } + } + }; + + + /** Register this test class... */ + LAUNCHER (VerbFunctionDispatch_test, "unit common"); + + + +}} // namespace lib::test diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 7d8b748d4..3ffbdc95e 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -7911,32 +7911,32 @@ Thus we'll employ a special kind of media asset, which actually links to a [[bin {{red{WIP as of 11/2010 -- most details yet to be defined}}} -
-
The ''Visitor Pattern'' is a special form of //double dispatch// &mdash; selecting the function actually to be executed at runtime based both on the concrete type of some tool object //and // the target this tool is applied to. The rationale is to separate some specific implementation details from the basic infrastructure and the global interfaces, which can be limited to describe the fundamental properties and operations, while all details relevant only for some specific sub-problem can be kept together encapsulated in a tool implementation class. Typically, there is some iteration mechanism, allowing to apply these tools to all objects in a given container, a collection or object graph, without knowing the exact type of the target and tool objects. See the [[Visitor Pattern design discussion|VisitorUse]]
+
+
The ''Visitor Pattern'' is a special form of //double dispatch// &mdash; the goal is to select  the function actually to be executed at runtime based both on the concrete type of some tool object //and// the target this tool is applied to. The rationale is to separate some specific implementation details from the basic infrastructure and the global interfaces, which can be limited to describe the fundamental properties and operations, while all details relevant only for some specific sub-problem can be kept together encapsulated in a tool implementation class. Typically, there is some iteration mechanism, allowing to apply these tools to all objects in a given container, a collection or object graph, without knowing the exact type of the target and tool objects. See the [[Visitor Pattern design discussion|VisitorUse]]
 
 !Problems with Visitor
-The visitor pattern is not very popular, because any implementation is tricky, difficult to understand and often puts quite some burden on the user code. Even Erich Gamma says that on his list of bottom-ten patterns, Visitor is at the very bottom. This may be due to the fact that this original visitor implementation (often called the ''~GoF visitor'') causes a cyclic dependency between the target objects and the visiting tool objects, and includes some repetitive code (which results in silent failure if forgotten). Robert Martin invented 1996 an interesting variation (commonly labled ''acyclic visitor''). By using a marker base class for each concrete target type to be treated by the visitor, and by applying a dynamic cast, we can get rid of the cyclic dependencies. The top level "Visitor" is reduced to a mere empty marker interface in this design, while the actual visiting capabilities for a concrete target object is discovered at application time by the aforementioned dynamic cast. Besides the runntime cost of such a cast, the catch is that now the user code has still more responsibilities, because the need to maintain consistently two parallel object hierarchies. 
-Long time there seemed to be not much room for improvement, at least before the advent of generic programming and the discovery of template metaprogramming. ''Loki'' (Alexandrescu, 2000) showed us how to write a library implementation which hides away the technicallities of the visitor pattern and automatically generates most of the repetitive code.
+The visitor pattern is not very popular, because any implementation is tricky, difficult to understand and tends to place quite some burden on the user code. Even Erich Gamma says that on his list of bottom-ten patterns, Visitor is at the very bottom. This may be due to the fact that this original visitor implementation (often called the ''~GoF visitor'') causes a cyclic dependency between the target objects and the visiting tool objects, and includes some repetitive code (which results in silent failure if forgotten). Robert Martin invented 1996 an interesting variation (commonly labelled ''acyclic visitor''). By using a marker base class for each concrete target type to be treated by the visitor, and by applying a dynamic cast, we can get rid of the cyclic dependencies. The top level "Visitor" is reduced to a mere empty marker interface in this design, while the actual visiting capabilities for a concrete target object is discovered at application time by the aforementioned dynamic cast. Besides the runtime cost of such a cast, the catch is that now the user code has still more responsibilities, because the need to maintain consistently two parallel object hierarchies. 
+Long time there seemed to be not much room for improvement, at least before the advent of generic programming and the discovery of template metaprogramming. ''Loki'' (Alexandrescu, 2000) showed us how to write a library implementation which hides away the technicalities of the visitor pattern and automatically generates most of the repetitive code.
 
 !Requirements
 * cyclic dependencies should be avoided or at least restricted to some central, library related place.
 * The responsibilities for user code should be as small as possible. Especially, we should minimize the necessity to do corresponding adjustments to separate code locations, e.g. the necessity to maintain parallel hierarchies.
 * Visitor is about //double dispatch,// thus we can't avoid using some table lookup implementation &mdash; more specifically we can't avoid using the cooperating classes vtables. We can expect at least two table lookups for each call dispatch. Besides that, the implementation should not be too wasteful...
-* individual "visiting tool" implementation classes should be able to opt in or opt out on implementing functions treating some of the visitable subclasses.
+* individual "visiting tool" implementation classes should be able to opt in or opt out on implementing functions to treat some of the visitable subclasses.
 * there should be a safe fallback mechanism backed by the visitable object's hierarchy relations. If some concrete visiting tool class decides not to implement a {{{treat(..)}}}-function for some concrete target type, the call should fall back to the next best match according to the target object's hierarchy, i.e. the next best {{{treat(..)}}}-function should be used.
-The last requirement practically rules out the Loki acyclic visitor, because this implementation calls a general fallback function when an exact match based on the target object's type is not possible. Considering our use of the visitor pattern within the render engine builder, such a solution would not be of much use: Some specific builder tool may implement a {{{treat(CompoundClip&)}}}-function, while most of the other builder tools just implement a {{{treat(Clip&)}}}-function, thus handling any multichannel clip via the general clip interface. This is exactly the reason why we want to use visitor at first place. Isolate specific treatment, implement against interfaces.
+The last requirement practically rules out the Loki acyclic visitor, because this implementation calls a general fallback function when an exact match based on the target object's type is not possible. Considering our use of the visitor pattern within the render engine builder, such a solution would not be of much use: Some specific builder tool may implement a {{{treat(CompoundClip&)}}}-function, while most of the other builder tools just implement a {{{treat(Clip&)}}}-function, thus handling any multichannel clip via the general clip interface. This is exactly the reason why we want to use visitor at first place. Reduce the scope of specific treatment, implement against rather generic interfaces.
 
 !Implementation Notes
-A good starting point for understanding our library implementation of the visitor pattern is {{{tests/components/common/visitingtoolconcept.cpp}}}, which contains a all-in-one-file proof of concept implementation, on which the real implementation ({{{"common/visitor.hpp"}}}) was based.
+A good starting point to understand our library implementation of the visitor pattern is {{{tests/components/common/visitingtoolconcept.cpp}}}, which contains an complete, all-in-one-file proof of concept implementation, on which the real implementation ({{{"common/visitor.hpp"}}}) was based.
 * similar to Loki, we use a {{{Visitable}}} base class and a {{{Tool}}} base class (we prefer the name "Tool" over "Visitor", because it makes the intended use more clear).
 * the objects in the {{{Visitable}}} hierarchy implement an {{{apply(Tool&)}}}-function. This function needs to be implemented in a very specific manner, thus the {{{DEFINE_PROCESSABLE_BY}}} macro should be used when possible to insert the definition into a concrete {{{Visitable}}} class.
 * similar to the acyclic visitor, the concrete visiting tool classes inherit from {{{Applicable<TARGET, ...>}}} marker base classes, where the template parameter {{{TARGET}}} is the concrete Visitable type this tool wants to treat, either directly by defining a {{{treat(ConcreteVisitable&)}}}, or by falling back to some more general {{{treat(...)}}} function.
 * consequently our implementation is //rather not acyclic// &mdash; the concrete tool implementation depends on the full definition (header) of all concrete Visitables, but we avoid cyclic dependencies on the interface level. By using a typelist technique inspired by Loki, we can concentrate these dependencies in one single header file, which keeps things maintainable.
-* we use the {{{Applicable<TARGET, ...>}}} marker base classes to drive the generation of Dispatcher classes, each of which holds a table of trampoline functions for carrying out the actual double dispatch at call time. Each concrete Visitable using the {{{DEFINE_PROCESSABLE_BY}}}-macro generates a separate Dispatcher table containing slots for each concrete tool implementation class. To store and access the index position for these "call slots", we use a tag associated with the concrete visiting tool class, which can be retrieved by going though the tool's vtable
+* we use the {{{Applicable<TARGET, ...>}}} marker base classes to drive the generation of Dispatcher classes, each of which holds a table of trampoline functions to carry out the actual double dispatch at call time. Each concrete Visitable, by using the {{{DEFINE_PROCESSABLE_BY}}}-macro, causes the generation of a dedicated, separate Dispatcher table, holding call slots for each concrete tool implementation class. To store and access the index position for these "call slots", we use a tag associated with the concrete visiting tool class, which can be retrieved by going though the tool's vtable
 * __runtime cost__: the concrete tool's ctor stores the trampoline pointers (this could be optimized to be a "once per class" initialisation). Then, for each call, we have 2 virtual function calls and a lookup and call of the trampoline function, typically resulting in another virtual function call for resolving the {{{treat(..)}}} function on the concrete tool class
-* __extension possibilities__: while this system may seem complicated, you should note that it was designed with special focus on extension and implementing against interfaces:
-** not every Visitable subclass needs a separate Dispatcher. As a rule of thumb, only when some type needs to be treated separately within some concrete visiting tool (i.e. when there is the need of a {{{treat(MySpecialVisitable&)}}}), then this class should use the {{{DEFINE_PROCESSABLE_BY}}}-macro and thus define it's own {{{apply()}}}-function and Dispatcher. In all other cases, it is sufficient just to extend some existing Visitable, which thus will act as an interface with regards to the visiting tools.
-** because the possibility of utilizing virtual {{{treat(...)}}} functions, not every concrete visiting tool class needs to define a set of {{{Applicable<...>}}} base classes (and thus get a separate dispatcher slot). We need such only for each //unique set// of Applicables. All other concrete tools can extend existing tool implementations, sharing and partially extending the same set of virtual {{{treat()}}}-functions.
+* __extension possibilities__: while this system might seem overengineered, you should note the specific focus on extension and implementing against interfaces:
+** not every Visitable subclass requires to build a separate Dispatcher. As a rule of thumb, only when a class needs dedicated and specific treatment within some concrete visiting tool (i.e. when there is the need of a function {{{treat(MySpecialVisitable&)}}}), then this class should use the {{{DEFINE_PROCESSABLE_BY}}}-macro, leading to the definition of a distinct {{{apply()}}}-function and Dispatcher. In all other cases, it is sufficient just to extend some existing Visitable, which thus acts as an interface as far as visiting tools are concerned.
+** because of the possibility of utilising virtual {{{treat(...)}}} functions, not every concrete visiting tool class needs to define a set of {{{Applicable<...>}}} base classes (and thus get a separate dispatcher slot). We need such only for each //unique set// of Applicables. All other concrete tools can extend existing tool implementations, sharing and partially extending the same set of virtual {{{treat()}}}-functions.
 ** when adding a new "first class" Visitable, i.e. a concrete target class that needs to be treated separately in some visiting tool, the user needs to include the {{{DEFINE_PROCESSABLE_BY}}} macro and needs to make sure that all existing "first class" tool implementation classes include the Applicable base class for this new type. In this respect, our implementation is clearly "cyclic". (Generally speaking, the visitor pattern should not be used when the hierarchy of target objects is frequently extended and remoulded). But, when using the typelist facillity to define the Applicable base classes, we'll have one header file defining these collection of Applicables and thus we just need to add our new concrete Visitable to this header and recompile all tool implementation classes.
 ** when creating a new "~Visitable-and-Tool" hierarchy, the user should derive (or typedef) and parametrize the {{{Visitable}}}, {{{Tool}}} and {{{Applicable}}} templates, typically into a new namespace. An example can be seen in {{{proc/mobject/builder/buildertool.hpp}}}