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) Lumiera.org
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
28 #include "lib/test/run.hpp"
29 #include "lib/visitor.hpp"
30 #include "lib/format-string.hpp"
31 
32 #include <iostream>
33 
34 using util::_Fmt;
35 using std::string;
36 using std::cout;
37 
38 
39 namespace lib {
40 namespace visitor{
41 namespace test2 {
42 
43  typedef visitor::Tool<> Tool;
44 
45  class HomoSapiens : public Visitable<>
46  {
47  public:
48  DEFINE_PROCESSABLE_BY (Tool);
49  };
50 
51  class Boss : public HomoSapiens
52  {
53  public:
54  DEFINE_PROCESSABLE_BY (Tool);
55  };
56 
57  class BigBoss : public Boss
58  {
59  public:
60  DEFINE_PROCESSABLE_BY (Tool);
61  };
62 
63 
64  template<class BASE>
66  : public BASE
67  {
68  protected:
69  void talk_to (string guy)
70  {
71  cout << _Fmt{"Hello %s, nice to meet you...\n"} % guy;
72  }
73  };
74 
75  class Babbler
76  : public Applicable< Babbler,
77  Types<Boss,BigBoss>::List, // treat this types
78  VerboseVisitor<Tool> // intermediary base class
79  >
80  {
81  public:
82  void treat (Boss&) { talk_to("Boss"); }
83  void treat (BigBoss&) { talk_to("Big Boss"); }
84  };
85 
86  // the classes above comprise the standard use case,
87  // what follows covers rather exotic corner cases
88 
89 
90 
92  template<class RET>
93  struct Catched
94  {
95  RET onUnknown (HomoSapiens&) { cout << "we-do-everything-for-YOU!\n"; return RET(); }
96  };
97 
101 
102 #define DEFINE_HASTALAVISTA_PROCESSABLE \
103  virtual void apply (Hastalavista& tool) \
104  { return Chief::dispatchOp (*this, tool); }
105 
106 
108  class Leader : public Chief,
109  public Boss
110  {
111  public:
112  using HomoSapiens::apply;
113  DEFINE_HASTALAVISTA_PROCESSABLE;
114  };
115 
116  class Visionary : public Leader
117  {
118  DEFINE_HASTALAVISTA_PROCESSABLE;
119  };
120 
124  class Blatherer
125  : public Applicable< Blatherer,
126  Types<Visionary>::List, // get calls to Visionary dispatched
127  VerboseVisitor<Hastalavista> // note: different tool base class
128  >
129  {
130  public:
131  void treat (Leader&) { talk_to("Mr.Future"); }
132  };
133 
134 
135 
136 
137 
138 
139 
140  /*********************************************************************/
147  class VisitingToolExtended_test : public Test
148  {
149  virtual void run(Arg)
150  {
151  known_visitor_known_class();
152  visitor_not_visiting_some_class();
153  visiting_mixed_hierarchy();
154  }
155 
156  void known_visitor_known_class()
157  {
158  Boss x1;
159  BigBoss x2;
160 
161  // masquerade as HomoSapiens...
162  HomoSapiens& homo1 (x1);
163  HomoSapiens& homo2 (x2);
164 
165  cout << "=== Babbler meets Boss and BigBoss ===\n";
166  Babbler bab;
167  homo1.apply (bab);
168  homo2.apply (bab);
169  }
170 
171  void visitor_not_visiting_some_class()
172  {
173  HomoSapiens x1;
174  Leader x2;
175 
176  HomoSapiens& homo1 (x1);
177  HomoSapiens& homo2 (x2);
178 
179  cout << "=== Babbler meets HomoSapiens and Leader ===\n";
180  Babbler bab;
181  homo1.apply (bab); // doesn't visit HomoSapiens
182  homo2.apply (bab); // treats Leader as Boss
183  }
184 
185  void visiting_mixed_hierarchy()
186  {
187  Leader x1;
188  Visionary x2;
189 
190  HomoSapiens& homo1 (x1);
191  HomoSapiens& homo2 (x2);
192  Chief& chief1 (x1);
193  Chief& chief2 (x2);
194  Leader& lead1 (x1);
195  Leader& lead2 (x2);
196 
197  Blatherer bla;
198  cout << "=== Blatherer meets Leader and Visionary masqueraded as Chief ===\n";
199  chief1.apply (bla); // catch-all, because Blatherer doesn't declare to be applicalbe to Leader
200  chief2.apply (bla); // treat(Visionary&) resolved to treat(Leader&) as expected
201 
202  Babbler bab;
203  Tool& tool1 (bab);
204  cout << "=== Babbler masqueraded as Tool meets Leader and Visionary masqueraded as HomoSapiens ===\n";
205  homo1.apply (tool1); // because just going through the VTable, the dispatch works as expected
206  homo2.apply (tool1); // same here (in both cases, the call is resolved to treat(Boss&) as expected)
207 
208  cout << "=== Babbler masqueraded as Tool meets Leader and Visionary masqueraded as Leader ===\n";
209  lead1.apply (tool1); // nothing happens, because Leader here is treated by his HomoSapiens base
210  lead2.apply (tool1); // surprisingly the VTable mechanism is choosen here, resulting in an correct dispatch
211 
212  // note: the following doesn't compile (an this is a feature, not a bug):
213 
214  // "Chief chief" : is abstract, because the Visitable-Template enforces implementing
215  // the "apply(TOOL&)" function, either directly or via the
216  // DEFINE_PROCESSABLE_BY macro
217 
218  }
219  };
220 
221 
223  LAUNCHER (VisitingToolExtended_test, "unit common");
224 
225 
226 
227 }}} // 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:144
Marker interface or base class for all "Visitables".
Definition: visitor.hpp:197
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:107
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 ...
Simple 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:231
A library implementation of the Visitor Pattern tailored specifically to Lumiera&#39;s needs within the S...