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