dune-typetree  2.3.1
pairtraversal.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_PAIRTRAVERSAL_HH
5 #define DUNE_TYPETREE_PAIRTRAVERSAL_HH
6 
11 
12 namespace Dune {
13  namespace TypeTree {
14 
20 #ifndef DOXYGEN // these are all internals and not public API. Only access is using applyToTree().
21 
22  template<TreePathType::Type tpType>
23  struct ApplyToTreePair<tpType,StartTag,StartTag,true>
24  {
25 
26 #if HAVE_RVALUE_REFERENCES
27 
28  template<typename Node1, typename Node2, typename Visitor>
29  static void apply(Node1&& node1, Node2&& node2, Visitor&& visitor)
30  {
31  ApplyToTreePair<tpType,
32  typename remove_reference<Node1>::type::NodeTag,
33  typename remove_reference<Node2>::type::NodeTag
34  >::apply(std::forward<Node1>(node1),
35  std::forward<Node2>(node2),
36  std::forward<Visitor>(visitor),
37  TreePathFactory<tpType>::create(node1).mutablePath());
38  }
39 
40 #else
41 
42  // The next two methods do some nasty trickery to make sure that both trees
43  // are either const or non-const and that no mixed case can occur. For this
44  // purpose, the enable_if on the first method makes sure that it will only
45  // ever match if both trees are non-const, and the second method casts both
46  // trees to const before passing them on.
47  template<typename Node1, typename Node2, typename Visitor>
48  static
49  typename enable_if<!(IsConst<Node1>::Value || IsConst<Node2>::Value)>::type
50  apply(Node1& node1, Node2& node2, Visitor& visitor)
51  {
52  ApplyToTreePair<tpType,
53  typename Node1::NodeTag,
54  typename Node2::NodeTag
55  >::apply(node1,
56  node2,
57  visitor,
58  TreePathFactory<tpType>::create(node1).mutablePath());
59  }
60 
61  template<typename Node1, typename Node2, typename Visitor>
62  static void apply(const Node1& node1, const Node2& node2, Visitor& visitor)
63  {
64  ApplyToTreePair<tpType,
65  typename Node1::NodeTag,
66  typename Node2::NodeTag
67  >::apply(const_cast<const Node1&>(node1), // see previous method
68  const_cast<const Node2&>(node2), // for explanation
69  visitor,
70  TreePathFactory<tpType>::create(node1).mutablePath());
71  }
72 
73 
74  // The next two methods do some nasty trickery to make sure that both trees
75  // are either const or non-const and that no mixed case can occur. For this
76  // purpose, the enable_if on the first method makes sure that it will only
77  // ever match if both trees are non-const, and the second method casts both
78  // trees to const before passing them on.
79  template<typename Node1, typename Node2, typename Visitor>
80  static
81  typename enable_if<!(IsConst<Node1>::Value || IsConst<Node2>::Value)>::type
82  apply(Node1& node1, Node2& node2, const Visitor& visitor)
83  {
84  ApplyToTreePair<tpType,
85  typename Node1::NodeTag,
86  typename Node2::NodeTag
87  >::apply(node1,
88  node2,
89  visitor,
90  TreePathFactory<tpType>::create(node1).mutablePath());
91  }
92 
93  template<typename Node1, typename Node2, typename Visitor>
94  static void apply(const Node1& node1, const Node2& node2, const Visitor& visitor)
95  {
96  ApplyToTreePair<tpType,
97  typename Node1::NodeTag,
98  typename Node2::NodeTag
99  >::apply(const_cast<const Node1&>(node1), // see previous method
100  const_cast<const Node2&>(node2), // for explanation
101  visitor,
102  TreePathFactory<tpType>::create(node1).mutablePath());
103  }
104 
105 #endif // HAVE_RVALUE_REFERENCES
106 
107  };
108 
109 
110  // Do not visit nodes the visitor is not interested in
111  template<TreePathType::Type tpType, typename Tag1, typename Tag2>
112  struct ApplyToTreePair<tpType,Tag1,Tag2,false>
113  {
114  template<typename Node1, typename Node2, typename Visitor, typename TreePath>
115  static void apply(const Node1& node1, const Node2& node2, const Visitor& visitor, TreePath treePath)
116  {}
117  };
118 
119 
120  /*
121 
122  // LeafNode - again, this is easy: just do all three visits
123  template<TreePathType::Type tpType>
124  struct ApplyToTree<tpType,LeafNodeTag,LeafNodeTag,true>
125  {
126 
127  #if HAVE_RVALUE_REFERENCES
128 
129  template<typename N1, typename N2, typename V, typename TreePath>
130  static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp)
131  {
132  v.leaf(std::forward<N1>(n1),std::forward<N2>(n2),tp.view());
133  }
134 
135  #else
136 
137  template<typename N1, typename N2, typename V, typename TreePath>
138  static void apply(N1& n1, N2& n2, V& v, TreePath tp)
139  {
140  v.leaf(n1,n2,tp.view());
141  }
142 
143  template<typename N1, typename N2, typename V, typename TreePath>
144  static void apply(const N1& n1, const N2& n2, V& v, TreePath tp)
145  {
146  v.leaf(n1,n2,tp.view());
147  }
148 
149  template<typename N1, typename N2, typename V, typename TreePath>
150  static void apply(N1& n1, N2& n2, const V& v, TreePath tp)
151  {
152  v.leaf(n1,n2,tp.view());
153  }
154 
155  template<typename N1, typename N2, typename V, typename TreePath>
156  static void apply(const N1& n1, const N2& n2, const V& v, TreePath tp)
157  {
158  v.leaf(n1,n2,tp.view());
159  }
160 
161  #endif // HAVE_RVALUE_REFERENCES
162 
163  };
164  */
165 
166 
167  // Automatically pick the correct traversal algorithm for the two nodes
168  template<TreePathType::Type treePathType,typename FirstTag, typename SecondTag>
169  struct ApplyToTreePair<treePathType,FirstTag,SecondTag,true>
170  : public ApplyToGenericCompositeNodePair<treePathType>
171  {
172  };
173 
174 
175 
176  // ********************************************************************************
177  // Specialization for dynamic traversal and two PowerNodes -> use runtime iteration
178  // ********************************************************************************
179 
180  template<>
181  struct ApplyToTreePair<TreePathType::dynamic,PowerNodeTag,PowerNodeTag,true>
182  {
183 
184 #if HAVE_RVALUE_REFERENCES
185 
186  template<typename N1, typename N2, typename V, typename TreePath>
187  static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp)
188  {
189  v.pre(std::forward<N1>(n1),std::forward<N2>(n2),tp.view());
190  typedef typename remove_reference<N1>::type Node1;
191  typedef typename remove_reference<N2>::type Node2;
192  typedef typename Node1::template Child<0>::Type C1;
193  typedef typename Node2::template Child<0>::Type C2;
194  dune_static_assert(Node1::CHILDREN == Node2::CHILDREN,
195  "non-leaf nodes with different numbers of children " \
196  "are not allowed during simultaneous grid traversal");
197  const bool visit = std::remove_reference<V>::type
199  for (std::size_t k = 0; k < Node1::CHILDREN; ++k)
200  {
201  v.beforeChild(std::forward<N1>(n1),n1.child(k),std::forward<N2>(n2),n2.child(k),tp.view(),k);
202  tp.push_back(k);
203  ApplyToTreePair<TreePathType::dynamic, // we know that due to the specialization
204  typename C1::NodeTag,
205  typename C2::NodeTag,
206  visit>::apply(n1.child(k),
207  n2.child(k),
208  std::forward<V>(v),
209  tp);
210  tp.pop_back();
211  v.afterChild(std::forward<N1>(n1),n1.child(k),std::forward<N2>(n2),n2.child(k),tp.view(),k);
212  if (k < Node1::CHILDREN-1)
213  v.in(std::forward<N1>(n1),std::forward<N2>(n2),tp.view());
214  }
215  v.post(std::forward<N1>(n1),std::forward<N2>(n2),tp.view());
216  }
217 
218 #else
219 
220  template<typename N1, typename N2, typename V, typename TreePath>
221  static void apply(N1& n1, N2& n2, V& v, TreePath tp)
222  {
223  v.pre(n1,n2,tp.view());
224  typedef typename N1::template Child<0>::Type C1;
225  typedef typename N2::template Child<0>::Type C2;
226  dune_static_assert(N1::CHILDREN == N2::CHILDREN,
227  "non-leaf nodes with different numbers of children " \
228  "are not allowed during simultaneous grid traversal");
229  const bool visit = V::template VisitChild<N1,C1,N2,C2,typename TreePath::ViewType>::value;
230  for (std::size_t k = 0; k < N1::CHILDREN; ++k)
231  {
232  v.beforeChild(n1,n1.child(k),n2,n2.child(k),tp.view(),k);
233  tp.push_back(k);
234  ApplyToTreePair<TreePathType::dynamic, // we know that due to the specialization
235  typename C1::NodeTag,
236  typename C2::NodeTag,
237  visit>::apply(n1.child(k),
238  n2.child(k),
239  v,
240  tp);
241  tp.pop_back();
242  v.afterChild(n1,n1.child(k),n2,n2.child(k),tp.view(),k);
243  if (k < N1::CHILDREN-1)
244  v.in(n1,n2,tp.view());
245  }
246  v.post(n1,n2,tp.view());
247  }
248 
249  template<typename N1, typename N2, typename V, typename TreePath>
250  static void apply(const N1& n1, const N2& n2, V& v, TreePath tp)
251  {
252  v.pre(n1,n2,tp.view());
253  typedef typename N1::template Child<0>::Type C1;
254  typedef typename N2::template Child<0>::Type C2;
255  dune_static_assert(N1::CHILDREN == N2::CHILDREN,
256  "non-leaf nodes with different numbers of children " \
257  "are not allowed during simultaneous grid traversal");
258  const bool visit = V::template VisitChild<N1,C1,N2,C2,typename TreePath::ViewType>::value;
259  for (std::size_t k = 0; k < N1::CHILDREN; ++k)
260  {
261  v.beforeChild(n1,n1.child(k),n2,n2.child(k),tp.view(),k);
262  tp.push_back(k);
263  ApplyToTreePair<TreePathType::dynamic, // we know that due to the specialization
264  typename C1::NodeTag,
265  typename C2::NodeTag,
266  visit>::apply(n1.child(k),
267  n2.child(k),
268  v,
269  tp);
270  tp.pop_back();
271  v.afterChild(n1,n1.child(k),n2,n2.child(k),tp.view(),k);
272  if (k < N1::CHILDREN-1)
273  v.in(n1,n2,tp.view());
274  }
275  v.post(n1,n2,tp.view());
276  }
277 
278  template<typename N1, typename N2, typename V, typename TreePath>
279  static void apply(N1& n1, N2& n2, const V& v, TreePath tp)
280  {
281  v.pre(n1,n2,tp.view());
282  typedef typename N1::template Child<0>::Type C1;
283  typedef typename N2::template Child<0>::Type C2;
284  dune_static_assert(N1::CHILDREN == N2::CHILDREN,
285  "non-leaf nodes with different numbers of children " \
286  "are not allowed during simultaneous grid traversal");
287  const bool visit = V::template VisitChild<N1,C1,N2,C2,typename TreePath::ViewType>::value;
288  for (std::size_t k = 0; k < N1::CHILDREN; ++k)
289  {
290  v.beforeChild(n1,n1.child(k),n2,n2.child(k),tp.view(),k);
291  tp.push_back(k);
292  ApplyToTreePair<TreePathType::dynamic, // we know that due to the specialization
293  typename C1::NodeTag,
294  typename C2::NodeTag,
295  visit>::apply(n1.child(k),
296  n2.child(k),
297  v,
298  tp);
299  tp.pop_back();
300  v.afterChild(n1,n1.child(k),n2,n2.child(k),tp.view(),k);
301  if (k < N1::CHILDREN-1)
302  v.in(n1,n2,tp.view());
303  }
304  v.post(n1,n2,tp.view());
305  }
306 
307  template<typename N1, typename N2, typename V, typename TreePath>
308  static void apply(const N1& n1, const N2& n2, const V& v, TreePath tp)
309  {
310  v.pre(n1,n2,tp.view());
311  typedef typename N1::template Child<0>::Type C1;
312  typedef typename N2::template Child<0>::Type C2;
313  dune_static_assert(N1::CHILDREN == N2::CHILDREN,
314  "non-leaf nodes with different numbers of children " \
315  "are not allowed during simultaneous grid traversal");
316  const bool visit = V::template VisitChild<N1,C1,N2,C2,typename TreePath::ViewType>::value;
317  for (std::size_t k = 0; k < N1::CHILDREN; ++k)
318  {
319  v.beforeChild(n1,n1.child(k),n2,n2.child(k),tp.view(),k);
320  tp.push_back(k);
321  ApplyToTreePair<TreePathType::dynamic, // we know that due to the specialization
322  typename C1::NodeTag,
323  typename C2::NodeTag,
324  visit>::apply(n1.child(k),
325  n2.child(k),
326  v,
327  tp);
328  tp.pop_back();
329  v.afterChild(n1,n1.child(k),n2,n2.child(k),tp.view(),k);
330  if (k < N1::CHILDREN-1)
331  v.in(n1,n2,tp.view());
332  }
333  v.post(n1,n2,tp.view());
334  }
335 
336 #endif // HAVE_RVALUE_REFERENCES
337 
338  };
339 
340 #endif // DOXYGEN
341 
342 #if HAVE_RVALUE_REFERENCES || DOXYGEN
343 
345 
359  template<typename Tree1, typename Tree2, typename Visitor>
360  void applyToTreePair(Tree1&& tree1, Tree2&& tree2, Visitor&& visitor)
361  {
363  std::forward<Tree2>(tree2),
364  std::forward<Visitor>(visitor));
365  }
366 
367 #else
368 
369  template<typename Tree1, typename Tree2, typename Visitor>
370  void applyToTreePair(Tree1& tree1, Tree2& tree2, Visitor& visitor)
371  {
372  ApplyToTreePair<Visitor::treePathType>::apply(tree1,tree2,visitor);
373  }
374 
375  template<typename Tree1, typename Tree2, typename Visitor>
376  void applyToTreePair(const Tree1& tree1, const Tree2& tree2, Visitor& visitor)
377  {
378  ApplyToTreePair<Visitor::treePathType>::apply(tree1,tree2,visitor);
379  }
380 
381  template<typename Tree1, typename Tree2, typename Visitor>
382  void applyToTreePair(Tree1& tree1, Tree2& tree2, const Visitor& visitor)
383  {
384  ApplyToTreePair<Visitor::treePathType>::apply(tree1,tree2,visitor);
385  }
386 
387  template<typename Tree1, typename Tree2, typename Visitor>
388  void applyToTreePair(const Tree1& tree1, const Tree2& tree2, const Visitor& visitor)
389  {
390  ApplyToTreePair<Visitor::treePathType>::apply(tree1,tree2,visitor);
391  }
392 
393 #endif // HAVE_RVALUE_REFERENCES || DOXYGEN
394 
396 
397  } // namespace TypeTree
398 } //namespace Dune
399 
400 #endif // DUNE_TYPETREE_PAIRTRAVERSAL_HH
Definition: treepath.hh:26
static const TreePathType::Type treePathType
Definition: traversalutilities.hh:30
static const std::size_t value
Definition: compositenode.hh:38
Type
Definition: treepath.hh:26
void applyToTreePair(Tree1 &&tree1, Tree2 &&tree2, Visitor &&visitor)
Apply visitor to a pair of TypeTrees.
Definition: pairtraversal.hh:360