"Fossies" - the Fresh Open Source Software Archive 
Member "dune-typetree-2.8.0/dune/typetree/visitor.hh" (31 Aug 2021, 22121 Bytes) of package /linux/misc/dune/dune-typetree-2.8.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "visitor.hh" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.8.0_vs_2.9.0.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3
4 #ifndef DUNE_TYPETREE_VISITOR_HH
5 #define DUNE_TYPETREE_VISITOR_HH
6
7 #include <dune/typetree/treepath.hh>
8 #include <dune/typetree/utility.hh>
9
10 namespace Dune {
11 namespace TypeTree {
12
13 /** \addtogroup Tree Traversal
14 * \ingroup TypeTree
15 * \{
16 */
17
18 //! Visitor interface and base class for TypeTree visitors.
19 /**
20 * DefaultVisitor defines the interface for visitors that can be applied to a TypeTree
21 * using applyToTree(). Each method of the visitor is passed a node of the tree (either as
22 * a mutable or a const reference, depending on the constness of the tree applyToTree() was
23 * called with). The second argument is of type TreePath and denotes the exact position of the
24 * node within the TypeTree, encoded as child indices starting at the root node.
25 *
26 * In order to create a functioning visitor, an implementation will - in addition to providing the methods
27 * of this class - also have to contain the following template struct, which is used to determine
28 * whether to visit a given node:
29 *
30 * \code
31 * template<typename Node, typename Child, typename TreePath>
32 * struct VisitChild
33 * {
34 * static const bool value = ...; // decide whether to visit Child
35 * };
36 * \endcode
37 *
38 * For the two most common scenarios - visiting only direct children and visiting the whole tree - there
39 * are mixin classes VisitDirectChildren and VisitTree and combined base classes TreeVisitor and
40 * DirectChildrenVisitor. The latter two inherit from both DefaultVisitor and one of the two mixin classes
41 * and can thus be used as convenient base classes.
42 *
43 * \note This class can also be used as a convenient base class if the implemented visitor
44 * only needs to act on some of the possible callback sites, avoiding a lot of boilerplate code.
45 */
46 struct DefaultVisitor
47 {
48
49 //! Method for prefix tree traversal.
50 /**
51 * This method gets called when first encountering a non-leaf node and
52 * before visiting any of its children.
53 *
54 * \param t The node to visit.
55 * \param treePath The position of the node within the TypeTree.
56 */
57 template<typename T, typename TreePath>
58 void pre(T&& t, TreePath treePath) const {}
59
60 //! Method for infix tree traversal.
61 /**
62 * This method gets called BETWEEN visits of children of a non-leaf node.
63 * That definition implies that this method will only be called for nodes
64 * with at least two children.
65 *
66 * \param t The node to visit.
67 * \param treePath The position of the node within the TypeTree.
68 */
69 template<typename T, typename TreePath>
70 void in(T&& t, TreePath treePath) const {}
71
72 //! Method for postfix tree traversal.
73 /**
74 * This method gets called after all children of a non-leaf node have
75 * been visited.
76 *
77 * \param t The node to visit.
78 * \param treePath The position of the node within the TypeTree.
79 */
80 template<typename T, typename TreePath>
81 void post(T&& t, TreePath treePath) const {}
82
83 //! Method for leaf traversal.
84 /**
85 * This method gets called when encountering a leaf node within the TypeTree.
86 *
87 * \param t The node to visit.
88 * \param treePath The position of the node within the TypeTree.
89 */
90 template<typename T, typename TreePath>
91 void leaf(T&& t, TreePath treePath) const {}
92
93 //! Method for parent-child traversal.
94 /**
95 * This method gets called before visiting a child node.
96 *
97 * \note This method gets called even if the visitor decides not to visit the child in question.
98 *
99 * \param t The parent node.
100 * \param child The child node that will (potentially) be visited next.
101 * \param treePath The position of the parent node within the TypeTree.
102 * \param childIndex The index of the child node in relation to the parent node.
103 */
104 template<typename T, typename Child, typename TreePath, typename ChildIndex>
105 void beforeChild(T&& t, Child&& child, TreePath treePath, ChildIndex childIndex) const {}
106
107 //! Method for child-parent traversal.
108 /**
109 * This method gets called after visiting a child node.
110 *
111 * \note This method gets called even if the child node was not visited because the visitor
112 * chose not to do so.
113 *
114 * \param t The parent node.
115 * \param child The child node that was visited last (if the visitor did not reject it).
116 * \param treePath The position of the parent node within the TypeTree.
117 * \param childIndex The index of the child node in relation to the parent node.
118 */
119 template<typename T, typename Child, typename TreePath, typename ChildIndex>
120 void afterChild(T&& t, Child&& child, TreePath treePath, ChildIndex childIndex) const {}
121
122 };
123
124
125 //! Visitor interface and base class for visitors of pairs of TypeTrees.
126 /**
127 * DefaultPairVisitor defines the interface for visitors that can be applied to a pair of TypeTrees
128 * using applyToTreePair(). Each method of the visitor is passed a node of both trees (either as
129 * a mutable or a const reference, depending on the constness of the tree applyToTreePair() was
130 * called with). The last argument is of type TreePath and denotes the exact position of the
131 * nodes within the TypeTrees, encoded as child indices starting at the root node.
132 *
133 * In order to create a functioning visitor, an implementation will - in addition to providing the methods
134 * of this class - also have to contain the following template struct, which is used to determine
135 * whether to visit a given node:
136 *
137 * \code
138 * template<typename Node1,
139 * typename Child1,
140 * typename Node2,
141 * typename Child2,
142 * typename TreePath>
143 * struct VisitChild
144 * {
145 * static const bool value = ...; // decide whether to visit Child
146 * };
147 * \endcode
148 *
149 * For the two most common scenarios - visiting only direct children and visiting the whole tree - there
150 * are mixin classes VisitDirectChildren and VisitTree and combined base classes TreePairVisitor and
151 * DirectChildrenPairVisitor. The latter two inherit from both DefaultVisitor and one of the two mixin classes
152 * and can thus be used as convenient base classes.
153 *
154 * \note If your compiler does not support rvalue references, both trees must be either const or
155 * non-const. If you call applyToTreePair() with two trees of different constness, they will
156 * both be made const.
157 *
158 * \note This class can also be used as a convenient base class if the implemented visitor
159 * only needs to act on some of the possible callback sites, avoiding a lot of boilerplate code.
160 */
161 struct DefaultPairVisitor
162 {
163
164 //! Method for prefix tree traversal.
165 /**
166 * This method gets called when first encountering a non-leaf node and
167 * before visiting any of its children.
168 *
169 * \param t1 The node of the first tree to visit.
170 * \param t2 The node of the second tree to visit.
171 * \param treePath The position of the node within the TypeTree.
172 */
173 template<typename T1, typename T2, typename TreePath>
174 void pre(T1&& t1, T2&& t2, TreePath treePath) const {}
175
176 //! Method for infix tree traversal.
177 /**
178 * This method gets called BETWEEN visits of children of a non-leaf node.
179 * That definition implies that this method will only be called for nodes
180 * with at least two children.
181 *
182 * \param t1 The node of the first tree to visit.
183 * \param t2 The node of the second tree to visit.
184 * \param treePath The position of the node within the TypeTree.
185 */
186 template<typename T1, typename T2, typename TreePath>
187 void in(T1&& t1, T2&& t2, TreePath treePath) const {}
188
189 //! Method for postfix traversal.
190 /**
191 * This method gets called after all children of a non-leaf node have
192 * been visited.
193 *
194 * \param t1 The node of the first tree to visit.
195 * \param t2 The node of the second tree to visit.
196 * \param treePath The position of the node within the TypeTree.
197 */
198 template<typename T1, typename T2, typename TreePath>
199 void post(T1&& t1, T2&& t2, TreePath treePath) const {}
200
201 //! Method for leaf traversal.
202 /**
203 * This method gets called when encountering a leaf node within the pair of TypeTrees.
204 *
205 * \attention Since the two TypeTrees are not required to be exactly identical,
206 * it is only guaranteed that at least one of the nodes is a leaf node,
207 * not both.
208 *
209 * \param t1 The node of the first tree to visit.
210 * \param t2 The node of the second tree to visit.
211 * \param treePath The position of the node within the TypeTree.
212 */
213 template<typename T1, typename T2, typename TreePath>
214 void leaf(T1&& t1, T2&& t2, TreePath treePath) const {}
215
216 //! Method for parent-child traversal.
217 /**
218 * This method gets called before visiting a child node.
219 *
220 * \note This method gets called even if the visitor decides not to visit the child in question.
221 *
222 * \param t1 The node of the first tree to visit.
223 * \param child1 The child of t1 to visit.
224 * \param t2 The node of the second tree to visit.
225 * \param child2 The child of t2 to visit.
226 * \param treePath The position of the parent nodes within the TypeTree.
227 * \param childIndex The index of the child nodes in relation to the parent nodes.
228 */
229 template<typename T1, typename Child1, typename T2, typename Child2, typename TreePath, typename ChildIndex>
230 void beforeChild(T1&& t1, Child1&& child1, T2&& t2, Child2&& child2, TreePath treePath, ChildIndex childIndex) const {}
231
232 //! Method for child-parent traversal.
233 /**
234 * This method gets called after visiting a child node.
235 *
236 * \note This method gets called even if the visitor decides not to visit the child in question.
237 *
238 * \param t1 The node of the first tree to visit.
239 * \param child1 The child of t1 to visit.
240 * \param t2 The node of the second tree to visit.
241 * \param child2 The child of t2 to visit.
242 * \param treePath The position of the parent nodes within the TypeTree.
243 * \param childIndex The index of the child nodes in relation to the parent nodes.
244 */
245 template<typename T1, typename Child1, typename T2, typename Child2, typename TreePath, typename ChildIndex>
246 void afterChild(T1&& t1, Child1&& child1, T2&& t2, Child2&& child2, TreePath treePath, ChildIndex childIndex) const {}
247
248 };
249
250
251 namespace Experimental {
252
253 /**
254 * @brief Hybrid visitor interface and base class for TypeTree hybrid visitors.
255 *
256 * DefaultHybridVisitor defines the interface for visitors that can be applied to a TypeTree
257 * using hybridApplyToTree(). Each method of the visitor is passed a node of the tree (either as
258 * a mutable or a const reference, depending on the constness of the tree hybridApplyToTree() was
259 * called with). The second argument is of type TreePath and denotes the exact position of the
260 * node within the TypeTree, encoded as child indices starting at the root node.
261 *
262 * An hybrid visitor is different from a plain visitor because each method receives a carried value
263 * (last argument) on the node visit and is required to return a transformed value from it.
264 * Transformations of the carried value type are allowed as long as they are expected on the
265 * next visited node.
266 *
267 * In order to create a functioning visitor, an implementation will - in addition to providing the methods
268 * of this class - also have to contain the following template struct, which is used to determine
269 * whether to visit a given node:
270 *
271 * \code
272 * template<typename Node, typename Child, typename TreePath>
273 * struct VisitChild
274 * {
275 * static const bool value = ...; // decide whether to visit Child
276 * };
277 * \endcode
278 *
279 *
280 * \note This class can also be used as a convenient base class if the implemented visitor
281 * only needs to act on some of the possible callback sites, avoiding a lot of boilerplate code.
282 */
283 struct DefaultHybridVisitor
284 {
285
286 /**
287 * \copybrief DefaultVisitor::pre
288 * \copydetails DefaultVisitor::pre
289 *
290 * \param u The carry value from previous visit.
291 * \return The result of applying this visitor to u.
292 */
293 template<typename T, typename TreePath, typename U>
294 auto pre(T&& t, TreePath treePath, const U& u) const { return u;}
295
296 /**
297 * \copybrief DefaultVisitor::in
298 * \copydetails DefaultVisitor::in
299 *
300 * \param u The carry value from previous visit.
301 * \return The result of applying this visitor to u.
302 */
303 template<typename T, typename TreePath, typename U>
304 auto in(T&& t, TreePath treePath, const U& u) const {return u;}
305
306 /**
307 * \copybrief DefaultVisitor::post
308 * \copydetails DefaultVisitor::post
309 *
310 * \param u The carry value from previous visit.
311 * \return The result of applying this visitor to u.
312 */
313 template<typename T, typename TreePath, typename U>
314 auto post(T&& t, TreePath treePath, const U& u) const {return u;}
315
316 /**
317 * \copybrief DefaultVisitor::leaf
318 * \copydetails DefaultVisitor::leaf
319 *
320 * \param u The carry value from previous visit.
321 * \return The result of applying this visitor to u.
322 */
323 template<typename T, typename TreePath, typename U>
324 auto leaf(T&& t, TreePath treePath, const U& u) const { return u;}
325
326 /**
327 * \copybrief DefaultVisitor::beforeChild
328 * \copydetails DefaultVisitor::beforeChild
329 *
330 * \param u The carry value from previous visit.
331 * \return The result of applying this visitor to u.
332 */
333 template<typename T, typename Child, typename TreePath, typename ChildIndex, typename U>
334 auto beforeChild(T&& t, Child&& child, TreePath treePath, ChildIndex childIndex, const U& u) const {return u;}
335
336 /**
337 * \copybrief DefaultVisitor::afterChild
338 * \copydetails DefaultVisitor::afterChild
339 *
340 * \param u The carry value from previous visit.
341 * \return The result of applying this visitor to u.
342 */
343 template<typename T, typename Child, typename TreePath, typename ChildIndex, typename U>
344 auto afterChild(T&& t, Child&& child, TreePath treePath, ChildIndex childIndex, const U& u) const {return u;}
345
346 };
347 } // namespace Experimental
348
349 //! Mixin base class for visitors that only want to visit the direct children of a node.
350 /**
351 * This mixin class will reject all children presented to it, causing the algorithm to
352 * only visit the root node and call DefaultVisitor::beforeChild() and DefaultVisitor::afterChild()
353 * for its direct children.
354 */
355 struct VisitDirectChildren
356 {
357
358 // the little trick with the default template arguments
359 // makes the class usable for both single-tree visitors
360 // and visitors for pairs of trees
361 //! Template struct for determining whether or not to visit a given child.
362 template<typename Node1,
363 typename Child1,
364 typename Node2,
365 typename Child2 = void,
366 typename TreePath = void>
367 struct VisitChild
368 {
369 //! Do not visit any child.
370 static const bool value = false;
371 };
372
373 };
374
375
376 //! Mixin base class for visitors that want to visit the complete tree.
377 /**
378 * This mixin class will accept all children presented to it and thus make the iterator
379 * traverse the entire tree.
380 */
381 struct VisitTree
382 {
383
384 // the little trick with the default template arguments
385 // makes the class usable for both single-tree visitors
386 // and visitors for pairs of trees
387 //! Template struct for determining whether or not to visit a given child.
388 template<typename Node1,
389 typename Child1,
390 typename Node2,
391 typename Child2 = void,
392 typename TreePath = void>
393 struct VisitChild
394 {
395 //! Visit any child.
396 static const bool value = true;
397 };
398
399 };
400
401 //! Mixin base class for visitors that require a static TreePath during traversal.
402 /**
403 * \warning Static traversal should only be used if absolutely necessary, as it tends
404 * to increase compilation times and object sizes (especially if compiling
405 * with debug information)!
406 *
407 * \sa DynamicTraversal
408 */
409 struct StaticTraversal
410 {
411 //! Use the static tree traversal algorithm.
412 static const TreePathType::Type treePathType = TreePathType::fullyStatic;
413 };
414
415 //! Mixin base class for visitors that only need a dynamic TreePath during traversal.
416 /**
417 * \note Dynamic traversal is preferable to static traversal, as it causes fewer
418 * template instantiations, which improves compile time and reduces object
419 * size (especially if compiling with debug information).
420 *
421 * \sa StaticTraversal
422 */
423 struct DynamicTraversal
424 {
425 //! Use the dynamic tree traversal algorithm.
426 static const TreePathType::Type treePathType = TreePathType::dynamic;
427 };
428
429 //! Convenience base class for visiting the entire tree.
430 struct TreeVisitor
431 : public DefaultVisitor
432 , public VisitTree
433 {};
434
435 //! Convenience base class for visiting the direct children of a node.
436 struct DirectChildrenVisitor
437 : public DefaultVisitor
438 , public VisitDirectChildren
439 {};
440
441 //! Convenience base class for visiting an entire tree pair.
442 struct TreePairVisitor
443 : public DefaultPairVisitor
444 , public VisitTree
445 {};
446
447 //! Convenience base class for visiting the direct children of a node pair.
448 struct DirectChildrenPairVisitor
449 : public DefaultPairVisitor
450 , public VisitDirectChildren
451 {};
452
453 namespace Experimental::Info {
454
455 struct LeafCounterVisitor
456 : public DefaultHybridVisitor
457 , public StaticTraversal
458 , public VisitTree
459 {
460 template<class Tree, class Child, class TreePath, class ChildIndex, class U>
461 auto beforeChild(Tree&&, Child&&, TreePath, ChildIndex, U u) const {
462 // in this case child index is an integral constant: forward u
463 return u;
464 }
465
466 template<class Tree, class Child, class TreePath, class U>
467 std::size_t beforeChild(Tree&&, Child&&, TreePath, std::size_t childIndex, U u) const {
468 // in this case child index is a run-time index: cast accumulated u to std::size_t
469 return std::size_t{u};
470 }
471
472 template<class Tree, class TreePath, class U>
473 auto leaf(Tree&&, TreePath, U u) const
474 {
475 return Hybrid::plus(u,Dune::Indices::_1);
476 }
477
478 };
479
480 struct NodeCounterVisitor
481 : public LeafCounterVisitor
482 {
483 template<typename Tree, typename TreePath, typename U>
484 auto pre(Tree&& tree, TreePath treePath, U u) const {
485 return Hybrid::plus(u,Indices::_1);
486 }
487 };
488
489 struct DepthVisitor
490 : public DefaultHybridVisitor
491 , public StaticTraversal
492 , public VisitTree
493 {
494 template<class Tree, class TreePath, class U>
495 auto leaf(Tree&&, TreePath, U u) const
496 {
497 auto path_size = index_constant<treePathSize(TreePath{})>{};
498 auto depth = Hybrid::plus(path_size,Indices::_1);
499 return Hybrid::max(depth,u);
500 }
501 };
502
503 //! The depth of the TypeTree.
504 // result is alwayas an integral constant
505 template<typename Tree>
506 auto depth(const Tree& tree)
507 {
508 return hybridApplyToTree(tree,DepthVisitor{},Indices::_0);
509 }
510
511 //! The depth of the Tree.
512 // return types is std::integral_constant.
513 template<typename Tree>
514 constexpr auto depth()
515 {
516 return decltype(hybridApplyToTree(std::declval<Tree>(),DepthVisitor{},Indices::_0)){};
517 }
518
519 //! The total number of nodes in the Tree.
520 // if Tree is dynamic, return type is std::size_t, otherwise std::integral_constant.
521 template<typename Tree>
522 auto nodeCount(const Tree& tree)
523 {
524 return hybridApplyToTree(tree,NodeCounterVisitor{},Indices::_0);
525 }
526
527 //! The number of leaf nodes in the Tree.
528 // if Tree is dynamic, return type is std::size_t, otherwise std::integral_constant.
529 template<typename Tree>
530 auto leafCount(const Tree& tree)
531 {
532 return hybridApplyToTree(tree,LeafCounterVisitor{},Dune::Indices::_0);
533 }
534
535 //! true if any of the nodes in the tree only has dynamic degree.
536 template<typename Tree>
537 constexpr bool isDynamic = std::is_same<std::size_t, decltype(leafCount(std::declval<Tree>()))>{};
538
539 } // namespace Experimental::Info
540
541 //! \} group Tree Traversal
542
543 } // namespace TypeTree
544 } //namespace Dune
545
546 #endif // DUNE_TYPETREE_VISITOR_HH