Lumiera  0.pre.03
»edit your freedom«
visitingtool-extended-test.cpp
Go to the documentation of this file.
1 /*
2  VisitingToolExtended(Test) - check obscure corner cases of visitor lib implementation
3 
4  Copyright (C)
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
19 #include "lib/test/run.hpp"
20 #include "lib/visitor.hpp"
21 #include "lib/format-string.hpp"
22 
23 #include <iostream>
24 
25 using util::_Fmt;
26 using std::string;
27 using std::cout;
28 
29 
30 namespace lib {
31 namespace visitor{
32 namespace test2 {
33 
34  typedef visitor::Tool<> Tool;
35 
36  class HomoSapiens : public Visitable<>
37  {
38  public:
39  DEFINE_PROCESSABLE_BY (Tool);
40  };
41 
42  class Boss : public HomoSapiens
43  {
44  public:
45  DEFINE_PROCESSABLE_BY (Tool);
46  };
47 
48  class BigBoss : public Boss
49  {
50  public:
51  DEFINE_PROCESSABLE_BY (Tool);
52  };
53 
54 
55  template<class BASE>
57  : public BASE
58  {
59  protected:
60  void talk_to (string guy)
61  {
62  cout << _Fmt{"Hello %s, nice to meet you...\n"} % guy;
63  }
64  };
65 
66  class Babbler
67  : public Applicable< Babbler,
68  Types<Boss,BigBoss>::List, // treat this types
69  VerboseVisitor<Tool> // intermediary base class
70  >
71  {
72  public:
73  void treat (Boss&) { talk_to("Boss"); }
74  void treat (BigBoss&) { talk_to("Big Boss"); }
75  };
76 
77  // the classes above comprise the standard use case,
78  // what follows covers rather exotic corner cases
79 
80 
81 
83  template<class RET>
84  struct Catched
85  {
86  RET onUnknown (HomoSapiens&) { cout << "we-do-everything-for-YOU!\n"; return RET(); }
87  };
88 
92 
93 #define DEFINE_HASTALAVISTA_PROCESSABLE \
94  virtual void apply (Hastalavista& tool) \
95  { return Chief::dispatchOp (*this, tool); }
96 
97 
99  class Leader : public Chief,
100  public Boss
101  {
102  public:
103  using HomoSapiens::apply;
104  DEFINE_HASTALAVISTA_PROCESSABLE;
105  };
106 
107  class Visionary : public Leader
108  {
109  DEFINE_HASTALAVISTA_PROCESSABLE;
110  };
111 
115  class Blatherer
116  : public Applicable< Blatherer,
117  Types<Visionary>::List, // get calls to Visionary dispatched
118  VerboseVisitor<Hastalavista> // note: different tool base class
119  >
120  {
121  public:
122  void treat (Leader&) { talk_to("Mr.Future"); }
123  };
124 
125 
126 
127 
128 
129 
130 
131  /*********************************************************************/
138  class VisitingToolExtended_test : public Test
139  {
140  virtual void run(Arg)
141  {
142  known_visitor_known_class();
143  visitor_not_visiting_some_class();
144  visiting_mixed_hierarchy();
145  }
146 
147  void known_visitor_known_class()
148  {
149  Boss x1;
150  BigBoss x2;
151 
152  // masquerade as HomoSapiens...
153  HomoSapiens& homo1 (x1);
154  HomoSapiens& homo2 (x2);
155 
156  cout << "=== Babbler meets Boss and BigBoss ===\n";
157  Babbler bab;
158  homo1.apply (bab);
159  homo2.apply (bab);
160  }
161 
162  void visitor_not_visiting_some_class()
163  {
164  HomoSapiens x1;
165  Leader x2;
166 
167  HomoSapiens& homo1 (x1);
168  HomoSapiens& homo2 (x2);
169 
170  cout << "=== Babbler meets HomoSapiens and Leader ===\n";
171  Babbler bab;
172  homo1.apply (bab); // doesn't visit HomoSapiens
173  homo2.apply (bab); // treats Leader as Boss
174  }
175 
176  void visiting_mixed_hierarchy()
177  {
178  Leader x1;
179  Visionary x2;
180 
181  HomoSapiens& homo1 (x1);
182  HomoSapiens& homo2 (x2);
183  Chief& chief1 (x1);
184  Chief& chief2 (x2);
185  Leader& lead1 (x1);
186  Leader& lead2 (x2);
187 
188  Blatherer bla;
189  cout << "=== Blatherer meets Leader and Visionary masqueraded as Chief ===\n";
190  chief1.apply (bla); // catch-all, because Blatherer doesn't declare to be applicalbe to Leader
191  chief2.apply (bla); // treat(Visionary&) resolved to treat(Leader&) as expected
192 
193  Babbler bab;
194  Tool& tool1 (bab);
195  cout << "=== Babbler masqueraded as Tool meets Leader and Visionary masqueraded as HomoSapiens ===\n";
196  homo1.apply (tool1); // because just going through the VTable, the dispatch works as expected
197  homo2.apply (tool1); // same here (in both cases, the call is resolved to treat(Boss&) as expected)
198 
199  cout << "=== Babbler masqueraded as Tool meets Leader and Visionary masqueraded as Leader ===\n";
200  lead1.apply (tool1); // nothing happens, because Leader here is treated by his HomoSapiens base
201  lead2.apply (tool1); // surprisingly the VTable mechanism is choosen here, resulting in an correct dispatch
202 
203  // note: the following doesn't compile (an this is a feature, not a bug):
204 
205  // "Chief chief" : is abstract, because the Visitable-Template enforces implementing
206  // the "apply(TOOL&)" function, either directly or via the
207  // DEFINE_PROCESSABLE_BY macro
208 
209  }
210  };
211 
212 
214  LAUNCHER (VisitingToolExtended_test, "unit common");
215 
216 
217 
218 }}} // namespace lib::visitor::test2
now mixing the two hierarchies...
Marker template to declare that some "visiting tool" wants to treat a set of concrete Visitable class...
Definition: visitor.hpp:135
Marker interface or base class for all "Visitables".
Definition: visitor.hpp:188
defines an catch-all-function instead of the silent default error handler
Front-end for printf-style string template interpolation.
A front-end for using printf-style formatting.
Marker interface / base class for all "visiting tools".
Definition: visitor.hpp:98
Implementation namespace for support and library code.
Hastalavista-Visiting-Tool tailored for the Chief hierarchy.
virtual ReturnType apply(Tool<> &)=0
to be defined by the DEFINE_PROCESSABLE_BY macro in all classes wanting to be treated by some tool ...
Simplistic test class runner.
#define DEFINE_PROCESSABLE_BY(TOOL)
mark a Visitable subclass as actually treat-able by some "visiting tool" base interface.
Definition: visitor.hpp:222
A library implementation of the Visitor Pattern tailored specifically to Lumiera&#39;s needs within the S...