dune-typetree  2.4.0-rc1
applytochildrentreepair.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_APPLYTOCHILDRENTREEPAIR_HH
5 #define DUNE_TYPETREE_APPLYTOCHILDRENTREEPAIR_HH
6 
7 #include <dune/common/typetraits.hh>
8 
11 #include <dune/typetree/visitor.hh>
12 
13 #include <utility>
14 
15 namespace Dune {
16  namespace TypeTree {
17 
23 #ifndef DOXYGEN // these are all internals and not public API. Only access is using applyToTree().
24 
25  // forward declaration of main engine struct
26  template<TreePathType::Type tpType, typename tag1 = StartTag, typename tag2 = StartTag, bool doApply = true>
27  struct ApplyToTreePair;
28 
29  namespace {
30 
31  // TMP for traversing the children of non-leaf nodes with a static TreePath.
32  // Due to the static TreePath, we have to use this TMP for both CompositeNode
33  // and PowerNode.
34  template<std::size_t inverse_k, std::size_t count>
35  struct apply_to_children_pair_fully_static
36  {
37 
38  template<typename N1, typename N2, typename V, typename TreePath>
39  static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp)
40  {
41  typedef typename remove_reference<N1>::type::template Child<count-inverse_k>::Type C1;
42  typedef typename remove_reference<N2>::type::template Child<count-inverse_k>::Type C2;
43  typedef typename TreePathPushBack<TreePath,count-inverse_k>::type ChildTreePath;
44  const bool visit = std::remove_reference<V>::type
45  ::template VisitChild<typename remove_reference<N1>::type,
46  C1,
47  typename remove_reference<N2>::type,
48  C2,
49  ChildTreePath>::value;
50  v.beforeChild(std::forward<N1>(n1),n1.template child<count-inverse_k>(),
51  std::forward<N2>(n2),n2.template child<count-inverse_k>(),
52  tp,integral_constant<std::size_t,count-inverse_k>());
54  typename C1::NodeTag,
55  typename C2::NodeTag,
56  visit>::apply(n1.template child<count-inverse_k>(),
57  n2.template child<count-inverse_k>(),
58  std::forward<V>(v),
59  ChildTreePath());
60  v.afterChild(std::forward<N1>(n1),n1.template child<count-inverse_k>(),
61  std::forward<N2>(n2),n2.template child<count-inverse_k>(),
62  tp,integral_constant<std::size_t,count-inverse_k>());
63  v.in(std::forward<N1>(n1),std::forward<N2>(n2),tp);
64  apply_to_children_pair_fully_static<inverse_k-1,count>::apply(std::forward<N1>(n1),
65  std::forward<N2>(n2),
66  std::forward<V>(v),
67  tp);
68  }
69 
70  };
71 
72  // Specialization for last child. This specialization stops the recursion and
73  // does not call the infix visitor.
74  template<std::size_t count>
75  struct apply_to_children_pair_fully_static<1,count>
76  {
77 
78  template<typename N1, typename N2, typename V, typename TreePath>
79  static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp)
80  {
81  typedef typename remove_reference<N1>::type::template Child<count-1>::Type C1;
82  typedef typename remove_reference<N2>::type::template Child<count-1>::Type C2;
83  typedef typename TreePathPushBack<TreePath,count-1>::type ChildTreePath;
84  const bool visit = std::remove_reference<V>::type
85  ::template VisitChild<typename remove_reference<N1>::type,
86  C1,
87  typename remove_reference<N2>::type,
88  C2,
89  ChildTreePath>::value;
90  v.beforeChild(std::forward<N1>(n1),n1.template child<count-1>(),
91  std::forward<N2>(n2),n2.template child<count-1>(),
92  tp,integral_constant<std::size_t,count-1>());
94  typename C1::NodeTag,
95  typename C2::NodeTag,
96  visit>::apply(n1.template child<count-1>(),
97  n2.template child<count-1>(),
98  std::forward<V>(v),
99  ChildTreePath());
100  v.afterChild(std::forward<N1>(n1),n1.template child<count-1>(),
101  std::forward<N2>(n2),n2.template child<count-1>(),
102  tp,integral_constant<std::size_t,count-1>());
103  }
104 
105  };
106 
107  // Specialization for CompositeNode without any children.
108  template<>
109  struct apply_to_children_pair_fully_static<0,0>
110  {
111 
112  template<typename N1, typename N2, typename V, typename TreePath>
113  static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp) {}
114 
115  };
116 
117 
118  // TMP for traversing the children of non-leaf nodes with a dynamic TreePath.
119  // This is used if at least one of the nodes is a CompositeNode.
120  // If both nodes are PowerNodes, this will not be instantiated and we simply
121  // use a runtime loop to iterate over the children.
122  template<std::size_t inverse_k, std::size_t count>
123  struct apply_to_children_pair_dynamic
124  {
125 
126  template<typename N1, typename N2, typename V, typename TreePath>
127  static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp)
128  {
129  typedef typename remove_reference<N1>::type::template Child<count-inverse_k>::Type C1;
130  typedef typename remove_reference<N2>::type::template Child<count-inverse_k>::Type C2;
131  const bool visit = std::remove_reference<V>::type
132  ::template VisitChild<typename remove_reference<N1>::type,
133  C1,
134  typename remove_reference<N2>::type,
135  C2,
136  typename TreePath::ViewType>::value;
137  v.beforeChild(std::forward<N1>(n1),n1.template child<count-inverse_k>(),
138  std::forward<N2>(n2),n2.template child<count-inverse_k>(),
139  tp.view(),count-inverse_k);
140  tp.push_back(count-inverse_k);
142  typename C1::NodeTag,
143  typename C2::NodeTag,
144  visit>::apply(n1.template child<count-inverse_k>(),
145  n2.template child<count-inverse_k>(),
146  std::forward<V>(v),
147  tp);
148  tp.pop_back();
149  v.afterChild(std::forward<N1>(n1),n1.template child<count-inverse_k>(),
150  std::forward<N2>(n2),n2.template child<count-inverse_k>(),
151  tp.view(),count-inverse_k);
152  v.in(std::forward<N1>(n1),std::forward<N2>(n2),tp.view());
153  apply_to_children_pair_dynamic<inverse_k-1,count>::apply(std::forward<N1>(n1),
154  std::forward<N2>(n2),
155  std::forward<V>(v),
156  tp);
157  }
158 
159  };
160 
161  // Specialization for last child. This specialization stops the recursion and
162  // does not call the infix visitor on the CompositeNode.
163  template<std::size_t count>
164  struct apply_to_children_pair_dynamic<1,count>
165  {
166 
167  template<typename N1, typename N2, typename V, typename TreePath>
168  static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp)
169  {
170  typedef typename remove_reference<N1>::type::template Child<count-1>::Type C1;
171  typedef typename remove_reference<N2>::type::template Child<count-1>::Type C2;
172  const bool visit = std::remove_reference<V>::type
173  ::template VisitChild<typename remove_reference<N1>::type,
174  C1,
175  typename remove_reference<N2>::type,
176  C2,
177  typename TreePath::ViewType>::value;
178  v.beforeChild(std::forward<N1>(n1),n1.template child<count-1>(),
179  std::forward<N2>(n2),n2.template child<count-1>(),
180  tp.view(),count-1);
181  tp.push_back(count-1);
183  typename C1::NodeTag,
184  typename C2::NodeTag,
185  visit>::apply(n1.template child<count-1>(),
186  n2.template child<count-1>(),
187  std::forward<V>(v),
188  tp);
189  tp.pop_back();
190  v.afterChild(std::forward<N1>(n1),n1.template child<count-1>(),
191  std::forward<N2>(n2),n2.template child<count-1>(),
192  tp.view(),count-1);
193  }
194 
195  };
196 
197  // Specialization for CompositeNode without any children.
198  template<>
199  struct apply_to_children_pair_dynamic<0,0>
200  {
201 
202  template<typename N1, typename N2, typename V, typename TreePath>
203  static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp) {}
204 
205  };
206 
207  // helper struct for automatically picking the correct child
208  // traversal algorithm variant
209  template<TreePathType::Type treePathType, std::size_t CHILDREN>
210  struct apply_to_children_pair;
211 
212  template<std::size_t CHILDREN>
213  struct apply_to_children_pair<TreePathType::fullyStatic,CHILDREN>
214  : public apply_to_children_pair_fully_static<CHILDREN,CHILDREN>
215  {};
216 
217  template<std::size_t CHILDREN>
218  struct apply_to_children_pair<TreePathType::dynamic,CHILDREN>
219  : public apply_to_children_pair_dynamic<CHILDREN,CHILDREN>
220  {};
221 
222 
223  } // anonymous namespace
224 
225 
226  // Base class for composite node traversal
227  template<TreePathType::Type treePathType>
228  struct ApplyToGenericCompositeNodePair
229  {
230 
231  // one node is a leaf -> treat node pair as a leaf
232  template<typename N1, typename N2, typename V, typename TreePath>
233  static typename enable_if<(remove_reference<N1>::type::isLeaf || remove_reference<N2>::type::isLeaf)>::type
234  apply(N1&& n1, N2&& n2, V&& v, TreePath tp)
235  {
236  v.leaf(std::forward<N1>(n1),std::forward<N2>(n2),tp.view());
237  }
238 
239  // both nodes contain children -> iterate over them
240  template<typename N1, typename N2, typename V, typename TreePath>
241  static typename enable_if<!(remove_reference<N1>::type::isLeaf || remove_reference<N2>::type::isLeaf)>::type
242  apply(N1&& n1, N2&& n2, V&& v, TreePath tp)
243  {
244  v.pre(std::forward<N1>(n1),std::forward<N2>(n2),tp.view());
245  typedef typename remove_reference<N1>::type Node1;
246  typedef typename remove_reference<N2>::type Node2;
247  // make sure both nodes have the same number of children - otherwise, it
248  // would be difficult to match the children to each other.
249  static_assert(Node1::CHILDREN == Node2::CHILDREN,
250  "non-leaf nodes with different numbers of children " \
251  "are not allowed during simultaneous grid traversal");
252  apply_to_children_pair<treePathType,Node1::CHILDREN>::apply(std::forward<N1>(n1),
253  std::forward<N2>(n2),
254  std::forward<V>(v),
255  tp);
256  v.post(std::forward<N1>(n1),std::forward<N2>(n2),tp.view());
257  }
258 
259  };
260 
261 
262 #endif // DOXYGEN
263 
265 
266  } // namespace TypeTree
267 } //namespace Dune
268 
269 #endif // DUNE_TYPETREE_APPLYTOCHILDRENTREEPAIR_HH
Definition: accumulate_static.hh:12
Definition: treepath.hh:26
Type
Definition: treepath.hh:26
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:568
static const TreePathType::Type treePathType
Definition: traversalutilities.hh:30
TreePath ViewType
Definition: treepath.hh:36