dune-typetree  2.5-dev
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 
12 #include <dune/typetree/visitor.hh>
13 
14 namespace Dune {
15  namespace TypeTree {
16 
22 #ifndef DOXYGEN // these are all internals and not public API.
23 
24  // forward declaration of main engine struct
25  template<TreePathType::Type tpType, typename tag = StartTag, bool doApply = true>
26  struct ApplyToTree;
27 
28  namespace {
29 
30  // For the CompositeNode, we do need a TMP for iterating over the
31  // children. Note that we use an index that counts down instead of up.
32  // This allows us to specialize the TMP for the last child, where we
33  // do not want to invoke the infix visitor on the CompositeNode.
34 
35  // There are two versions of this TMP, one for iteration with a static TreePath, and one
36  // for iteration with a dynamic TreePath.
37 
38 
39 
40 
41  // ********************************************************************************
42  // Static Version
43  // ********************************************************************************
44 
45  template<std::size_t inverse_k, std::size_t count>
46  struct apply_to_children_fully_static
47  {
48 
49  template<typename N, typename V, typename TreePath>
50  static void apply(N&& n, V&& v, TreePath tp)
51  {
52  // make sure we do not try to work with references to the actual types
53  typedef typename std::remove_reference<N>::type Node;
54  typedef typename std::remove_reference<V>::type Visitor;
55 
56  // get child type
57  typedef typename Node::template Child<count-inverse_k>::Type C;
58 
59  // extend TreePath by child index
60  typedef typename TreePathPushBack<TreePath,count-inverse_k>::type ChildTreePath;
61 
62  // is the visitor interested in this child?
63  const bool visit = Visitor::template VisitChild<Node,C,ChildTreePath>::value;
64 
65  // beforeChild() gets called regardless of the value of visit
66  v.beforeChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp,std::integral_constant<std::size_t,count-inverse_k>());
67 
68  // traverse to child
69  ApplyToTree<Visitor::treePathType,NodeTag<C>,visit>::apply(n.template child<count-inverse_k>(),
70  std::forward<V>(v),
71  ChildTreePath());
72 
73  // afterChild() gets called regardless of the value of visit
74  v.afterChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp,std::integral_constant<std::size_t,count-inverse_k>());
75 
76  // we are not at the last child (that is specialized), so call infix visitor callback
77  v.in(std::forward<N>(n),tp);
78 
79  // continue with next child
80  apply_to_children_fully_static<inverse_k-1,count>::apply(std::forward<N>(n),
81  std::forward<V>(v),
82  tp);
83  }
84 
85  };
86 
87  // Specialization for last child. This specialization stops the recursion and
88  // does not call the infix visitor on the CompositeNode.
89  template<std::size_t count>
90  struct apply_to_children_fully_static<1,count>
91  {
92 
93  template<typename N, typename V, typename TreePath>
94  static void apply(N&& n, V&& v, TreePath tp)
95  {
96  typedef typename std::remove_reference<N>::type Node;
97  typedef typename std::remove_reference<V>::type Visitor;
98  typedef typename Node::template Child<count-1>::Type C;
99  typedef typename TreePathPushBack<TreePath,count-1>::type ChildTreePath;
100  const bool visit = Visitor::template VisitChild<Node,C,ChildTreePath>::value;
101  v.beforeChild(std::forward<N>(n),n.template child<count-1>(),tp,std::integral_constant<std::size_t,count-1>());
102  ApplyToTree<Visitor::treePathType,NodeTag<C>,visit>::apply(n.template child<count-1>(),
103  std::forward<V>(v),
104  ChildTreePath());
105  v.afterChild(std::forward<N>(n),n.template child<count-1>(),tp,std::integral_constant<std::size_t,count-1>());
106  }
107 
108  };
109 
110  // Specialization for CompositeNode without any children.
111  template<>
112  struct apply_to_children_fully_static<0,0>
113  {
114 
115  template<typename N, typename V, typename TreePath>
116  static void apply(N&& n, V&& v, TreePath tp) {}
117 
118  };
119 
120 
121 
122 
123  // ********************************************************************************
124  // Dynamic Version
125  // ********************************************************************************
126 
127  template<std::size_t inverse_k, std::size_t count>
128  struct apply_to_children_dynamic
129  {
130 
131  template<typename N, typename V, typename TreePath>
132  static void apply(N&& n, V&& v, TreePath tp)
133  {
134  typedef typename std::remove_reference<N>::type Node;
135  typedef typename std::remove_reference<V>::type Visitor;
136  typedef typename Node::template Child<count-inverse_k>::Type C;
137  const bool visit = Visitor::template VisitChild<Node,C,typename TreePath::ViewType>::value;
138  v.beforeChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
139  tp.push_back(count-inverse_k);
140  ApplyToTree<Visitor::treePathType,NodeTag<C>,visit>::apply(n.template child<count-inverse_k>(),
141  std::forward<V>(v),
142  tp);
143  tp.pop_back();
144  v.afterChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
145  v.in(std::forward<N>(n),tp.view());
146  apply_to_children_dynamic<inverse_k-1,count>::apply(std::forward<N>(n),
147  std::forward<V>(v),
148  tp);
149  }
150 
151  };
152 
153  // Specialization for last child. This specialization stops the recursion and
154  // does not call the infix visitor on the CompositeNode.
155  template<std::size_t count>
156  struct apply_to_children_dynamic<1,count>
157  {
158 
159  template<typename N, typename V, typename TreePath>
160  static void apply(N&& n, V&& v, TreePath tp)
161  {
162  typedef typename std::remove_reference<N>::type Node;
163  typedef typename std::remove_reference<V>::type Visitor;
164  typedef typename Node::template Child<count-1>::Type C;
165  const bool visit = Visitor::template VisitChild<Node,C,typename TreePath::ViewType>::value;
166  v.beforeChild(std::forward<N>(n),n.template child<count-1>(),tp.view(),count-1);
167  tp.push_back(count-1);
168  ApplyToTree<Visitor::treePathType,NodeTag<C>,visit>::apply(n.template child<count-1>(),
169  std::forward<V>(v),
170  tp);
171  tp.pop_back();
172  v.afterChild(std::forward<N>(n),n.template child<count-1>(),tp.view(),count-1);
173  }
174 
175  };
176 
177  // Specialization for CompositeNode without any children.
178  template<>
179  struct apply_to_children_dynamic<0,0>
180  {
181 
182  template<typename N, typename V, typename TreePath>
183  static void apply(N&& n, V&& v, TreePath tp) {}
184 
185  };
186 
187 
188  // helper struct for automatically picking the right traversal
189  // algorithm variant
190  template<TreePathType::Type treePathType, std::size_t CHILDREN>
191  struct apply_to_children;
192 
193  template<std::size_t CHILDREN>
194  struct apply_to_children<TreePathType::fullyStatic,CHILDREN>
195  : public apply_to_children_fully_static<CHILDREN,CHILDREN>
196  {};
197 
198  template<std::size_t CHILDREN>
199  struct apply_to_children<TreePathType::dynamic,CHILDREN>
200  : public apply_to_children_dynamic<CHILDREN,CHILDREN>
201  {};
202 
203 
204  } // anonymous namespace
205 
206 
207 
208  // Base class for composite node traversal
209 
210  // The traversal algorithm is identical for CompositeNode
211  // and PowerNode in the case of static traversal,
212  // so the implementation can be bundled
213  // in a single base class.
214  struct ApplyToGenericCompositeNode
215  {
216 
217  template<typename N, typename V, typename TreePath>
218  static void apply(N&& n, V&& v, TreePath tp)
219  {
220  v.pre(std::forward<N>(n),tp);
221  typedef typename std::remove_reference<N>::type Node;
222  typedef typename std::remove_reference<V>::type Visitor;
223  apply_to_children<Visitor::treePathType,StaticDegree<Node>::value>::apply(std::forward<N>(n),
224  std::forward<V>(v),
225  tp);
226  v.post(std::forward<N>(n),tp);
227  }
228 
229  };
230 
231 #endif // DOXYGEN
232 
234 
235  } // namespace TypeTree
236 } //namespace Dune
237 
238 #endif // DUNE_TYPETREE_APPLYTOCHILDRENSINGLETREE_HH
typename impl::_Child< Node, indices... >::type Child
Template alias for the type of a child node given by a list of child indices.
Definition: childextraction.hh:307
Definition: accumulate_static.hh:13
Definition: treepath.hh:26
Type
Definition: treepath.hh:26