DUNE PDELab (2.8)

childextraction.hh
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
14
15#include <dune/typetree/nodeinterface.hh>
16#include <dune/typetree/treepath.hh>
17
18
19namespace Dune {
20 namespace TypeTree {
21
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
102
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
146
169 template<typename Node, typename... Indices>
170#ifdef DOXYGEN
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
215
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
241
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
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<
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<
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
316
317 } // namespace TypeTree
318} //namespace Dune
319
320#endif // DUNE_TYPETREE_CHILDEXTRACTION_HH
A hybrid version of TreePath that supports both compile time and run time indices.
Definition: treepath.hh:79
Infrastructure for concepts.
Documentation related stuff.
Traits for type conversions and type information.
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:28
std::size_t degree(const Node &node)
Returns the degree of node as run time information.
Definition: nodeinterface.hh:76
constexpr std::size_t treePathSize(const HybridTreePath< T... > &)
Returns the size (number of components) of the given HybridTreePath.
Definition: treepath.hh:196
constexpr HybridTreePath< T... > treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:188
typename impl::_is_flat_index< std::decay_t< T > >::type is_flat_index
Type trait that determines whether T is a flat index in the context of child extraction.
Definition: childextraction.hh:282
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:223
typename impl::_ChildForTreePath< Node, TreePath >::type ChildForTreePath
Template alias for the type of a child node given by a TreePath or a HybridTreePath type.
Definition: childextraction.hh:250
ImplementationDefined child(Node &&node, HybridTreePath< Indices... > treePath)
Extracts the child of a node given by a HybridTreePath object.
Definition: childextraction.hh:171
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:49
Dune namespace.
Definition: alignedallocator.hh:11
This file implements several utilities related to std::shared_ptr.
Dummy struct used for documentation purposes.
Definition: documentation.hh:40
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 22, 23:30, 2024)