dune-typetree  2.3.1
applytochildrensingletree.hh
Go to the documentation of this file.
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_APPLYTOCHILDRENSINGLETREE_HH
5 #define DUNE_TYPETREE_APPLYTOCHILDRENSINGLETREE_HH
6 
7 #include <dune/common/typetraits.hh>
8 
11 #include <dune/typetree/visitor.hh>
12 
13 namespace Dune {
14  namespace TypeTree {
15 
21 #ifndef DOXYGEN // these are all internals and not public API.
22 
23  // forward declaration of main engine struct
24  template<TreePathType::Type tpType, typename tag = StartTag, bool doApply = true>
25  struct ApplyToTree;
26 
27  namespace {
28 
29  // For the CompositeNode, we do need a TMP for iterating over the
30  // children. Note that we use an index that counts down instead of up.
31  // This allows us to specialize the TMP for the last child, where we
32  // do not want to invoke the infix visitor on the CompositeNode.
33 
34  // There are two versions of this TMP, one for iteration with a static TreePath, and one
35  // for iteration with a dynamic TreePath.
36 
37 
38 
39 
40  // ********************************************************************************
41  // Static Version
42  // ********************************************************************************
43 
44  template<std::size_t inverse_k, std::size_t count>
45  struct apply_to_children_fully_static
46  {
47 
48 #if HAVE_RVALUE_REFERENCES
49 
50  template<typename N, typename V, typename TreePath>
51  static void apply(N&& n, V&& v, TreePath tp)
52  {
53  // make sure we do not try to work with references to the actual types
54  typedef typename remove_reference<N>::type Node;
55  typedef typename remove_reference<V>::type Visitor;
56 
57  // get child type
58  typedef typename Node::template Child<count-inverse_k>::Type C;
59 
60  // extend TreePath by child index
61  typedef typename TreePathPushBack<TreePath,count-inverse_k>::type ChildTreePath;
62 
63  // is the visitor interested in this child?
64  const bool visit = Visitor::template VisitChild<Node,C,ChildTreePath>::value;
65 
66  // beforeChild() gets called regardless of the value of visit
67  v.beforeChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
68 
69  // traverse to child
70  ApplyToTree<Visitor::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),
71  std::forward<V>(v),
72  ChildTreePath());
73 
74  // afterChild() gets called regardless of the value of visit
75  v.afterChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
76 
77  // we are not at the last child (that is specialized), so call infix visitor callback
78  v.in(std::forward<N>(n),tp);
79 
80  // continue with next child
81  apply_to_children_fully_static<inverse_k-1,count>::apply(std::forward<N>(n),
82  std::forward<V>(v),
83  tp);
84  }
85 
86 #else
87 
88  // non-const tree, non-const visitor
89  template<typename N, typename V, typename TreePath>
90  static void apply(N& n, V& v, TreePath tp)
91  {
92  typedef typename N::template Child<count-inverse_k>::Type C;
93  typedef typename TreePathPushBack<TreePath,count-inverse_k>::type ChildTreePath;
94  const bool visit = V::template VisitChild<N,C,ChildTreePath>::value;
95  v.beforeChild(n,n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
96  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),v,ChildTreePath());
97  v.afterChild(n,n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
98  v.in(n,tp);
99  apply_to_children_fully_static<inverse_k-1,count>::apply(n,v,tp);
100  }
101 
102  // const tree, non-const visitor
103  template<typename N, typename V, typename TreePath>
104  static void apply(const N& n, V& v, TreePath tp)
105  {
106  typedef typename N::template Child<count-inverse_k>::Type C;
107  typedef typename TreePathPushBack<TreePath,count-inverse_k>::type ChildTreePath;
108  const bool visit = V::template VisitChild<N,C,ChildTreePath>::value;
109  v.beforeChild(n,n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
110  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),v,ChildTreePath());
111  v.afterChild(n,n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
112  v.in(n,tp);
113  apply_to_children_fully_static<inverse_k-1,count>::apply(n,v,tp);
114  }
115 
116  // non-const tree, const visitor
117  template<typename N, typename V, typename TreePath>
118  static void apply(N& n, const V& v, TreePath tp)
119  {
120  typedef typename N::template Child<count-inverse_k>::Type C;
121  typedef typename TreePathPushBack<TreePath,count-inverse_k>::type ChildTreePath;
122  const bool visit = V::template VisitChild<N,C,ChildTreePath>::value;
123  v.beforeChild(n,n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
124  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),v,ChildTreePath());
125  v.afterChild(n,n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
126  v.in(n,tp);
127  apply_to_children_fully_static<inverse_k-1,count>::apply(n,v,tp);
128  }
129 
130  // const tree, const visitor
131  template<typename N, typename V, typename TreePath>
132  static void apply(const N& n, const V& v, TreePath tp)
133  {
134  typedef typename N::template Child<count-inverse_k>::Type C;
135  typedef typename TreePathPushBack<TreePath,count-inverse_k>::type ChildTreePath;
136  const bool visit = V::template VisitChild<N,C,ChildTreePath>::value;
137  v.beforeChild(n,n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
138  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),v,ChildTreePath());
139  v.afterChild(n,n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
140  v.in(n,tp);
141  apply_to_children_fully_static<inverse_k-1,count>::apply(n,v,tp);
142  }
143 
144 #endif // HAVE_RVALUE_REFERENCES
145 
146  };
147 
148  // Specialization for last child. This specialization stops the recursion and
149  // does not call the infix visitor on the CompositeNode.
150  template<std::size_t count>
151  struct apply_to_children_fully_static<1,count>
152  {
153 
154 #if HAVE_RVALUE_REFERENCES
155 
156  template<typename N, typename V, typename TreePath>
157  static void apply(N&& n, V&& v, TreePath tp)
158  {
159  typedef typename remove_reference<N>::type Node;
160  typedef typename remove_reference<V>::type Visitor;
161  typedef typename Node::template Child<count-1>::Type C;
162  typedef typename TreePathPushBack<TreePath,count-1>::type ChildTreePath;
163  const bool visit = Visitor::template VisitChild<Node,C,ChildTreePath>::value;
164  v.beforeChild(std::forward<N>(n),n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
165  ApplyToTree<Visitor::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),
166  std::forward<V>(v),
167  ChildTreePath());
168  v.afterChild(std::forward<N>(n),n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
169  }
170 
171 #else
172 
173  // non-const tree, non-const visitor
174  template<typename N, typename V, typename TreePath>
175  static void apply(N& n, V& v, TreePath tp)
176  {
177  typedef typename N::template Child<count-1>::Type C;
178  typedef typename TreePathPushBack<TreePath,count-1>::type ChildTreePath;
179  const bool visit = V::template VisitChild<N,C,ChildTreePath>::value;
180  v.beforeChild(n,n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
181  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),v,ChildTreePath());
182  v.afterChild(n,n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
183  }
184 
185  // const tree, non-const visitor
186  template<typename N, typename V, typename TreePath>
187  static void apply(const N& n, V& v, TreePath tp)
188  {
189  typedef typename N::template Child<count-1>::Type C;
190  typedef typename TreePathPushBack<TreePath,count-1>::type ChildTreePath;
191  const bool visit = V::template VisitChild<N,C,ChildTreePath>::value;
192  v.beforeChild(n,n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
193  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),v,ChildTreePath());
194  v.afterChild(n,n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
195  }
196 
197  // non-const tree, const visitor
198  template<typename N, typename V, typename TreePath>
199  static void apply(N& n, const V& v, TreePath tp)
200  {
201  typedef typename N::template Child<count-1>::Type C;
202  typedef typename TreePathPushBack<TreePath,count-1>::type ChildTreePath;
203  const bool visit = V::template VisitChild<N,C,ChildTreePath>::value;
204  v.beforeChild(n,n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
205  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),v,ChildTreePath());
206  v.afterChild(n,n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
207  }
208 
209  // const tree, const visitor
210  template<typename N, typename V, typename TreePath>
211  static void apply(const N& n, const V& v, TreePath tp)
212  {
213  typedef typename N::template Child<count-1>::Type C;
214  typedef typename TreePathPushBack<TreePath,count-1>::type ChildTreePath;
215  const bool visit = V::template VisitChild<N,C,ChildTreePath>::value;
216  v.beforeChild(n,n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
217  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),v,ChildTreePath());
218  v.afterChild(n,n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
219  }
220 
221 #endif // HAVE_RVALUE_REFERENCES
222  };
223 
224  // Specialization for CompositeNode without any children.
225  template<>
226  struct apply_to_children_fully_static<0,0>
227  {
228 
229 #if HAVE_RVALUE_REFERENCES
230 
231  template<typename N, typename V, typename TreePath>
232  static void apply(N&& n, V&& v, TreePath tp) {}
233 
234 #else
235 
236  template<typename N, typename V, typename TreePath>
237  static void apply(N& n, V& v, TreePath tp) {}
238 
239  template<typename N, typename V, typename TreePath>
240  static void apply(const N& n, V& v, TreePath tp) {}
241 
242  template<typename N, typename V, typename TreePath>
243  static void apply(N& n, const V& v, TreePath tp) {}
244 
245  template<typename N, typename V, typename TreePath>
246  static void apply(const N& n, const V& v, TreePath tp) {}
247 
248 #endif // HAVE_RVALUE_REFERENCES
249 
250  };
251 
252 
253 
254 
255  // ********************************************************************************
256  // Dynamic Version
257  // ********************************************************************************
258 
259  template<std::size_t inverse_k, std::size_t count>
260  struct apply_to_children_dynamic
261  {
262 
263 #if HAVE_RVALUE_REFERENCES
264 
265  template<typename N, typename V, typename TreePath>
266  static void apply(N&& n, V&& v, TreePath tp)
267  {
268  typedef typename remove_reference<N>::type Node;
269  typedef typename remove_reference<V>::type Visitor;
270  typedef typename Node::template Child<count-inverse_k>::Type C;
271  const bool visit = Visitor::template VisitChild<Node,C,typename TreePath::ViewType>::value;
272  v.beforeChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
273  tp.push_back(count-inverse_k);
274  ApplyToTree<Visitor::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),
275  std::forward<V>(v),
276  tp);
277  tp.pop_back();
278  v.afterChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
279  v.in(std::forward<N>(n),tp.view());
280  apply_to_children_dynamic<inverse_k-1,count>::apply(std::forward<N>(n),
281  std::forward<V>(v),
282  tp);
283  }
284 
285 #else
286 
287  template<typename N, typename V, typename TreePath>
288  static void apply(N& n, V& v, TreePath tp)
289  {
290  typedef typename N::template Child<count-inverse_k>::Type C;
291  const bool visit = V::template VisitChild<N,C,typename TreePath::ViewType>::value;
292  v.beforeChild(n,n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
293  tp.push_back(count-inverse_k);
294  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),
295  v,
296  tp);
297  tp.pop_back();
298  v.afterChild(n,n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
299  v.in(n,tp.view());
300  apply_to_children_dynamic<inverse_k-1,count>::apply(n,v,tp);
301  }
302 
303  template<typename N, typename V, typename TreePath>
304  static void apply(const N& n, V& v, TreePath tp)
305  {
306  typedef typename N::template Child<count-inverse_k>::Type C;
307  const bool visit = V::template VisitChild<N,C,typename TreePath::ViewType>::value;
308  v.beforeChild(n,n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
309  tp.push_back(count-inverse_k);
310  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),
311  v,
312  tp);
313  tp.pop_back();
314  v.afterChild(n,n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
315  v.in(n,tp.view());
316  apply_to_children_dynamic<inverse_k-1,count>::apply(n,v,tp);
317  }
318 
319  template<typename N, typename V, typename TreePath>
320  static void apply(N& n, const V& v, TreePath tp)
321  {
322  typedef typename N::template Child<count-inverse_k>::Type C;
323  const bool visit = V::template VisitChild<N,C,typename TreePath::ViewType>::value;
324  v.beforeChild(n,n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
325  tp.push_back(count-inverse_k);
326  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),
327  v,
328  tp);
329  tp.pop_back();
330  v.afterChild(n,n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
331  v.in(n,tp.view());
332  apply_to_children_dynamic<inverse_k-1,count>::apply(n,v,tp);
333  }
334 
335  template<typename N, typename V, typename TreePath>
336  static void apply(const N& n, const V& v, TreePath tp)
337  {
338  typedef typename N::template Child<count-inverse_k>::Type C;
339  const bool visit = V::template VisitChild<N,C,typename TreePath::ViewType>::value;
340  v.beforeChild(n,n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
341  tp.push_back(count-inverse_k);
342  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),
343  v,
344  tp);
345  tp.pop_back();
346  v.afterChild(n,n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
347  v.in(n,tp.view());
348  apply_to_children_dynamic<inverse_k-1,count>::apply(n,v,tp);
349  }
350 
351 #endif // HAVE_RVALUE_REFERENCES
352 
353  };
354 
355  // Specialization for last child. This specialization stops the recursion and
356  // does not call the infix visitor on the CompositeNode.
357  template<std::size_t count>
358  struct apply_to_children_dynamic<1,count>
359  {
360 
361 #if HAVE_RVALUE_REFERENCES
362 
363  template<typename N, typename V, typename TreePath>
364  static void apply(N&& n, V&& v, TreePath tp)
365  {
366  typedef typename remove_reference<N>::type Node;
367  typedef typename remove_reference<V>::type Visitor;
368  typedef typename Node::template Child<count-1>::Type C;
369  const bool visit = Visitor::template VisitChild<Node,C,typename TreePath::ViewType>::value;
370  v.beforeChild(std::forward<N>(n),n.template child<count-1>(),tp.view(),count-1);
371  tp.push_back(count-1);
372  ApplyToTree<Visitor::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),
373  std::forward<V>(v),
374  tp);
375  tp.pop_back();
376  v.afterChild(std::forward<N>(n),n.template child<count-1>(),tp.view(),count-1);
377  }
378 
379 #else
380 
381  template<typename N, typename V, typename TreePath>
382  static void apply(N& n, V& v, TreePath tp)
383  {
384  typedef typename N::template Child<count-1>::Type C;
385  const bool visit = V::template VisitChild<N,C,typename TreePath::ViewType>::value;
386  v.beforeChild(n,n.template child<count-1>(),tp.view(),count-1);
387  tp.push_back(count-1);
388  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),
389  v,
390  tp);
391  tp.pop_back();
392  v.afterChild(n,n.template child<count-1>(),tp.view(),count-1);
393  }
394 
395  template<typename N, typename V, typename TreePath>
396  static void apply(const N& n, V& v, TreePath tp)
397  {
398  typedef typename N::template Child<count-1>::Type C;
399  const bool visit = V::template VisitChild<N,C,typename TreePath::ViewType>::value;
400  v.beforeChild(n,n.template child<count-1>(),tp.view(),count-1);
401  tp.push_back(count-1);
402  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),
403  v,
404  tp);
405  tp.pop_back();
406  v.afterChild(n,n.template child<count-1>(),tp.view(),count-1);
407  }
408 
409  template<typename N, typename V, typename TreePath>
410  static void apply(N& n, const V& v, TreePath tp)
411  {
412  typedef typename N::template Child<count-1>::Type C;
413  const bool visit = V::template VisitChild<N,C,typename TreePath::ViewType>::value;
414  v.beforeChild(n,n.template child<count-1>(),tp.view(),count-1);
415  tp.push_back(count-1);
416  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),
417  v,
418  tp);
419  tp.pop_back();
420  v.afterChild(n,n.template child<count-1>(),tp.view(),count-1);
421  }
422 
423  template<typename N, typename V, typename TreePath>
424  static void apply(const N& n, const V& v, TreePath tp)
425  {
426  typedef typename N::template Child<count-1>::Type C;
427  const bool visit = V::template VisitChild<N,C,typename TreePath::ViewType>::value;
428  v.beforeChild(n,n.template child<count-1>(),tp.view(),count-1);
429  tp.push_back(count-1);
430  ApplyToTree<V::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),
431  v,
432  tp);
433  tp.pop_back();
434  v.afterChild(n,n.template child<count-1>(),tp.view(),count-1);
435  }
436 
437 #endif // HAVE_RVALUE_REFERENCES
438  };
439 
440  // Specialization for CompositeNode without any children.
441  template<>
442  struct apply_to_children_dynamic<0,0>
443  {
444 
445 #if HAVE_RVALUE_REFERENCES
446 
447  template<typename N, typename V, typename TreePath>
448  static void apply(N&& n, V&& v, TreePath tp) {}
449 
450 #else
451 
452  template<typename N, typename V, typename TreePath>
453  static void apply(N& n, V& v, TreePath tp) {}
454 
455  template<typename N, typename V, typename TreePath>
456  static void apply(const N& n, V& v, TreePath tp) {}
457 
458  template<typename N, typename V, typename TreePath>
459  static void apply(N& n, const V& v, TreePath tp) {}
460 
461  template<typename N, typename V, typename TreePath>
462  static void apply(const N& n, const V& v, TreePath tp) {}
463 
464 #endif // HAVE_RVALUE_REFERENCES
465 
466  };
467 
468 
469  // helper struct for automatically picking the right traversal
470  // algorithm variant
471  template<TreePathType::Type treePathType, std::size_t CHILDREN>
472  struct apply_to_children;
473 
474  template<std::size_t CHILDREN>
475  struct apply_to_children<TreePathType::fullyStatic,CHILDREN>
476  : public apply_to_children_fully_static<CHILDREN,CHILDREN>
477  {};
478 
479  template<std::size_t CHILDREN>
480  struct apply_to_children<TreePathType::dynamic,CHILDREN>
481  : public apply_to_children_dynamic<CHILDREN,CHILDREN>
482  {};
483 
484 
485  } // anonymous namespace
486 
487 
488 
489  // Base class for composite node traversal
490 
491  // The traversal algorithm is identical for CompositeNode and VariadicCompositeNode
492  // (and even PowerNode for static traversal), so the implementation can be bundled
493  // in a single base class.
494  struct ApplyToGenericCompositeNode
495  {
496 
497 #if HAVE_RVALUE_REFERENCES
498 
499  template<typename N, typename V, typename TreePath>
500  static void apply(N&& n, V&& v, TreePath tp)
501  {
502  v.pre(std::forward<N>(n),tp);
503  typedef typename remove_reference<N>::type Node;
504  typedef typename remove_reference<V>::type Visitor;
505  apply_to_children<Visitor::treePathType,Node::CHILDREN>::apply(std::forward<N>(n),
506  std::forward<V>(v),
507  tp);
508  v.post(std::forward<N>(n),tp);
509  }
510 
511 #else
512 
513  template<typename N, typename V, typename TreePath>
514  static void apply(N& n, V& v, TreePath tp)
515  {
516  v.pre(n,tp);
517  apply_to_children<V::treePathType,N::CHILDREN>::apply(n,v,tp);
518  v.post(n,tp);
519  }
520 
521  template<typename N, typename V, typename TreePath>
522  static void apply(const N& n, V& v, TreePath tp)
523  {
524  v.pre(n,tp);
525  apply_to_children<V::treePathType,N::CHILDREN>::apply(n,v,tp);
526  v.post(n,tp);
527  }
528 
529  template<typename N, typename V, typename TreePath>
530  static void apply(N& n, const V& v, TreePath tp)
531  {
532  v.pre(n,tp);
533  apply_to_children<V::treePathType,N::CHILDREN>::apply(n,v,tp);
534  v.post(n,tp);
535  }
536 
537  template<typename N, typename V, typename TreePath>
538  static void apply(const N& n, const V& v, TreePath tp)
539  {
540  v.pre(n,tp);
541  apply_to_children<V::treePathType,N::CHILDREN>::apply(n,v,tp);
542  v.post(n,tp);
543  }
544 
545 #endif // HAVE_RVALUE_REFERENCES
546 
547  };
548 
549 #endif // DOXYGEN
550 
552 
553  } // namespace TypeTree
554 } //namespace Dune
555 
556 #endif // DUNE_TYPETREE_APPLYTOCHILDRENSINGLETREE_HH
Definition: treepath.hh:26
static const std::size_t value
Definition: compositenode.hh:38
Type
Definition: treepath.hh:26