"Fossies" - the Fresh Open Source Software Archive 
Member "dune-typetree-2.8.0/dune/typetree/childextraction.hh" (31 Aug 2021, 10642 Bytes) of package /linux/misc/dune/dune-typetree-2.8.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "childextraction.hh" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.8.0_vs_2.9.0.
1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=8 sw=2 sts=2:
3
4 #ifndef DUNE_TYPETREE_CHILDEXTRACTION_HH
5 #define DUNE_TYPETREE_CHILDEXTRACTION_HH
6
7 #include <type_traits>
8 #include <utility>
9
10 #include <dune/common/concept.hh>
11 #include <dune/common/documentation.hh>
12 #include <dune/common/typetraits.hh>
13 #include <dune/common/shared_ptr.hh>
14
15 #include <dune/typetree/nodeinterface.hh>
16 #include <dune/typetree/treepath.hh>
17
18
19 namespace Dune {
20 namespace TypeTree {
21
22 //! \addtogroup TypeTreeChildExtraction Child Extraction
23 //! Utility functions and metafunctions for extracting children from a TypeTree.
24 //! \ingroup TypeTree
25 //! \{
26
27 #ifndef DOXYGEN
28
29 namespace Impl {
30
31 // check at run time whether index is a valid child index
32 template <class Node, class Index>
33 std::true_type checkChildIndex (Node const& node, Index i)
34 {
35 assert(std::size_t(i) < node.degree() && "Child index out of range");
36 return {};
37 }
38
39 // check at compile time whether index is a valid index
40 template <class Node, std::size_t i>
41 std::bool_constant<(i < Node::degree())> checkChildIndex (Node const& node, index_constant<i>)
42 {
43 static_assert(i < Node::degree(), "Child index out of range");
44 return {};
45 }
46
47 // finally return the node itself if no further indices are provided. Break condition
48 // for the recursion over the node childs.
49 template<class Node>
50 decltype(auto) childImpl (Node&& node)
51 {
52 return std::forward<Node>(node);
53 }
54
55 template<class NodePtr>
56 auto childStorageImpl (NodePtr&& nodePtr)
57 {
58 return std::forward<NodePtr>(nodePtr);
59 }
60
61 // recursively call `node.child(...)` with the given indices
62 template<class Node, class I0, class... I>
63 decltype(auto) childImpl (Node&& node, I0 i0, I... i)
64 {
65 auto valid = checkChildIndex(node,i0);
66 if constexpr (valid)
67 return childImpl(node.child(i0),i...);
68 else
69 return;
70 }
71
72 // recursively call `node.childStorage(...)` with the given indices
73 template<class NodePtr, class I0, class... I>
74 decltype(auto) childStorageImpl (NodePtr&& nodePtr, I0 i0, I... i)
75 {
76 auto valid = checkChildIndex(*nodePtr,i0);
77 if constexpr (valid)
78 return childStorageImpl(nodePtr->childStorage(i0),i...);
79 else
80 return;
81 }
82
83 // forward to the impl methods by extracting the indices from the treepath
84 template<class Node, class... Indices, std::size_t... i>
85 decltype(auto) child (Node&& node, HybridTreePath<Indices...> tp, std::index_sequence<i...>)
86 {
87 return childImpl(std::forward<Node>(node),treePathEntry<i>(tp)...);
88 }
89
90 // forward to the impl methods by extracting the indices from the treepath
91 template<class NodePtr, class... Indices, std::size_t... i>
92 decltype(auto) childStorage (NodePtr&& nodePtr, HybridTreePath<Indices...> tp, std::index_sequence<i...>)
93 {
94 return childStorageImpl(std::forward<NodePtr>(nodePtr),treePathEntry<i>(tp)...);
95 }
96
97 } // end namespace Impl
98
99 #endif // DOXYGEN
100
101 //! Extracts the child of a node given by a sequence of compile-time and run-time indices.
102 /**
103 * Use this function to extract a (possibly indirect) child of a TypeTree node.
104 *
105 * Example:
106 *
107 * \code{.cc}
108 * using namespace Dune::Indices; // for compile-time indices
109 * auto&& c = child(node,_4,2,_0,1);
110 * \endcode
111 *
112 * returns the second child of the first child of the third child
113 * of the fifth child of node, where some child lookups were done using
114 * a compile-time index and some using a run-time index.
115 *
116 * \param node The node from which to extract the child.
117 * \param indices... A list of indices that describes the path into the tree to the
118 * wanted child. These parameters can be a combination of run time indices
119 * (for tree nodes that allow accessing their children using run time information,
120 * like PowerNode) and instances of index_constant, which work for all types of inner
121 * nodes.
122 * \return A reference to the child, its cv-qualification depends on the passed-in node.
123 */
124 template<typename Node, typename... Indices>
125 #ifdef DOXYGEN
126 ImplementationDefined child (Node&& node, Indices... indices)
127 #else
128 decltype(auto) child (Node&& node, Indices... indices)
129 #endif
130 {
131 return Impl::childImpl(std::forward<Node>(node),indices...);
132 }
133
134 template<typename Node, typename... Indices>
135 #ifdef DOXYGEN
136 ImplementationDefined childStorage (Node&& node, Indices... indices)
137 #else
138 auto childStorage (Node&& node, Indices... indices)
139 #endif
140 {
141 static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty list of child indices");
142 return Impl::childStorageImpl(&node,indices...);
143 }
144
145 //! Extracts the child of a node given by a HybridTreePath object.
146 /**
147 * Use this function to extract a (possibly indirect) child of a TypeTree node.
148 *
149 * Example:
150 *
151 * \code{.cc}
152 * using namespace Dune::TypeTree::Indices; // for compile-time indices
153 * auto tp = Dune::TypeTree::hybridTreePath(_4,2,_0,1);
154 * auto&& c = child(node,tp);
155 * \endcode
156 *
157 * returns the second child of the first child of the third child
158 * of the fifth child of node, where some child lookups were done using
159 * a compile-time index and some using a run-time index.
160 *
161 * \param node The node from which to extract the child.
162 * \param tree{ath A HybridTreePath that describes the path into the tree to the
163 * wanted child. This tree path object can be a combination of run time indices
164 * (for tree nodes that allow accessing their children using run time information,
165 * like PowerNode) and instances of index_constant, which work for all types of inner
166 * nodes.
167 * \return A reference to the child, its cv-qualification depends on the passed-in node.
168 */
169 template<typename Node, typename... Indices>
170 #ifdef DOXYGEN
171 ImplementationDefined child (Node&& node, HybridTreePath<Indices...> treePath)
172 #else
173 decltype(auto) child (Node&& node, HybridTreePath<Indices...> tp)
174 #endif
175 {
176 return Impl::child(std::forward<Node>(node),tp,std::index_sequence_for<Indices...>{});
177 }
178
179 template<typename Node, typename... Indices>
180 #ifdef DOXYGEN
181 ImplementationDefined child (Node&& node, HybridTreePath<Indices...> treePath)
182 #else
183 auto childStorage (Node&& node, HybridTreePath<Indices...> tp)
184 #endif
185 {
186 static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty TreePath");
187 return Impl::childStorage(&node,tp,std::index_sequence_for<Indices...>{});
188 }
189
190
191 #ifndef DOXYGEN
192
193 namespace impl {
194
195 template<typename T>
196 struct filter_void
197 {
198 using type = T;
199 };
200
201 template<>
202 struct filter_void<void>
203 {};
204
205 template<typename Node, std::size_t... indices>
206 struct _Child
207 : public filter_void<std::decay_t<decltype(child(std::declval<Node>(),index_constant<indices>{}...))>>
208 {};
209
210 }
211
212 #endif // DOXYGEN
213
214 //! Template alias for the type of a child node given by a list of child indices.
215 /**
216 * This template alias is implemented in terms of the free-standing child() functions and uses those
217 * in combination with decltype() to extract the child type.
218
219 * \tparam Node The type of the parent node.
220 * \tparam indices A list of index values the describes the path to the wanted child.
221 */
222 template<typename Node, std::size_t... indices>
223 using Child = typename impl::_Child<Node,indices...>::type;
224
225
226 #ifndef DOXYGEN
227
228 namespace impl {
229
230 template<typename Node, typename TreePath>
231 struct _ChildForTreePath
232 {
233 using type = typename std::decay<decltype(child(std::declval<Node>(),std::declval<TreePath>()))>::type;
234 };
235
236 }
237
238 #endif // DOXYGEN
239
240 //! Template alias for the type of a child node given by a TreePath or a HybridTreePath type.
241 /**
242 * This template alias is implemented in terms of the free-standing child() functions and uses those
243 * in combination with decltype() to extract the child type. It supports both TreePath and
244 * HybridTreePath.
245 *
246 * \tparam Node The type of the parent node.
247 * \tparam TreePath The type of a TreePath or a HybridTreePath that describes the path to the wanted child.
248 */
249 template<typename Node, typename TreePath>
250 using ChildForTreePath = typename impl::_ChildForTreePath<Node,TreePath>::type;
251
252
253 #ifndef DOXYGEN
254
255 namespace impl {
256
257 // By default, types are flat indices if they are integral
258 template<typename T>
259 struct _is_flat_index
260 {
261 using type = std::is_integral<T>;
262 };
263
264 // And so is any index_constant
265 template<std::size_t i>
266 struct _is_flat_index<index_constant<i>>
267 {
268 using type = std::true_type;
269 };
270
271 }
272
273 #endif // DOXYGEN
274
275 //! Type trait that determines whether T is a flat index in the context of child extraction.
276 /*
277 * This type trait can be used to check whether T is a flat index (i.e. either `std::size_t`
278 * or `index_constant`). The type trait normalizes T before doing the check, so it will also
279 * work correctly for references and cv-qualified types.
280 */
281 template<typename T>
282 using is_flat_index = typename impl::_is_flat_index<std::decay_t<T>>::type;
283
284 #ifndef DOXYGEN
285
286 namespace impl {
287
288 // helper function for check in member child() functions that tolerates being passed something that
289 // isn't a TreePath. It will just return 0 in that case
290
291 template<typename T>
292 constexpr typename std::enable_if<
293 Dune::TypeTree::is_flat_index<T>::value,
294 bool
295 >::type
296 _non_empty_tree_path (T)
297 {
298 return false;
299 }
300
301 template<typename T>
302 constexpr typename std::enable_if<
303 !Dune::TypeTree::is_flat_index<T>::value,
304 bool
305 >::type
306 _non_empty_tree_path (T t)
307 {
308 return treePathSize(t) > 0;
309 }
310
311 }
312
313 #endif // DOXYGEN
314
315 //! \} group TypeTree
316
317 } // namespace TypeTree
318 } //namespace Dune
319
320 #endif // DUNE_TYPETREE_CHILDEXTRACTION_HH