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
13
14#include <utility>
15
16namespace 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>());
54 ApplyToTreePair<std::remove_reference<V>::type::treePathType,
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>());
94 ApplyToTreePair<std::remove_reference<V>::type::treePathType,
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);
142 ApplyToTreePair<std::remove_reference<V>::type::treePathType,
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);
183 ApplyToTreePair<std::remove_reference<V>::type::treePathType,
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
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
@ fullyStatic
Definition treepath.hh:26
@ dynamic
Definition treepath.hh:26