DUNE PDELab (git)

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// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-GPL-2.0-only-with-PDELab-exception
5
6#ifndef DUNE_TYPETREE_CHILDEXTRACTION_HH
7#define DUNE_TYPETREE_CHILDEXTRACTION_HH
8
9#include <type_traits>
10#include <utility>
11
16
17#include <dune/typetree/nodeinterface.hh>
18#include <dune/typetree/treepath.hh>
19
20
21namespace Dune {
22 namespace TypeTree {
23
28
29#ifndef DOXYGEN
30
31 namespace Impl {
32
33 // check at run time whether index is a valid child index
34 template <class Node, class Index>
35 std::true_type checkChildIndex (Node const& node, Index i)
36 {
37 assert(std::size_t(i) < node.degree() && "Child index out of range");
38 return {};
39 }
40
41 // check at compile time whether index is a valid index
42 template <class Node, std::size_t i>
43 std::bool_constant<(i < Node::degree())> checkChildIndex (Node const& node, index_constant<i>)
44 {
45 static_assert(i < Node::degree(), "Child index out of range");
46 return {};
47 }
48
49 // finally return the node itself if no further indices are provided. Break condition
50 // for the recursion over the node childs.
51 template<class Node>
52 decltype(auto) childImpl (Node&& node)
53 {
54 return std::forward<Node>(node);
55 }
56
57 template<class NodePtr>
58 auto childStorageImpl (NodePtr&& nodePtr)
59 {
60 return std::forward<NodePtr>(nodePtr);
61 }
62
63 // recursively call `node.child(...)` with the given indices
64 template<class Node, class I0, class... I>
65 decltype(auto) childImpl (Node&& node, I0 i0, [[maybe_unused]] I... i)
66 {
67 auto valid = checkChildIndex(node,i0);
68 if constexpr (valid)
69 return childImpl(node.child(i0),i...);
70 else
71 return;
72 }
73
74 // recursively call `node.childStorage(...)` with the given indices
75 template<class NodePtr, class I0, class... I>
76 decltype(auto) childStorageImpl (NodePtr&& nodePtr, I0 i0, [[maybe_unused]] I... i)
77 {
78 auto valid = checkChildIndex(*nodePtr,i0);
79 if constexpr (valid)
80 return childStorageImpl(nodePtr->childStorage(i0),i...);
81 else
82 return;
83 }
84
85 // forward to the impl methods by extracting the indices from the treepath
86 template<class Node, class... Indices, std::size_t... i>
87 decltype(auto) child (Node&& node, [[maybe_unused]] HybridTreePath<Indices...> tp, std::index_sequence<i...>)
88 {
89 return childImpl(std::forward<Node>(node),treePathEntry<i>(tp)...);
90 }
91
92 // forward to the impl methods by extracting the indices from the treepath
93 template<class NodePtr, class... Indices, std::size_t... i>
94 decltype(auto) childStorage (NodePtr&& nodePtr, [[maybe_unused]] HybridTreePath<Indices...> tp, std::index_sequence<i...>)
95 {
96 return childStorageImpl(std::forward<NodePtr>(nodePtr),treePathEntry<i>(tp)...);
97 }
98
99 } // end namespace Impl
100
101#endif // DOXYGEN
102
104
126 template<typename Node, typename... Indices>
127#ifdef DOXYGEN
128 ImplementationDefined child (Node&& node, Indices... indices)
129#else
130 decltype(auto) child (Node&& node, Indices... indices)
131#endif
132 {
133 return Impl::childImpl(std::forward<Node>(node),indices...);
134 }
135
136 template<typename Node, typename... Indices>
137#ifdef DOXYGEN
138 ImplementationDefined childStorage (Node&& node, Indices... indices)
139#else
140 auto childStorage (Node&& node, Indices... indices)
141#endif
142 {
143 static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty list of child indices");
144 return Impl::childStorageImpl(&node,indices...);
145 }
146
148
171 template<typename Node, typename... Indices>
172#ifdef DOXYGEN
174#else
175 decltype(auto) child (Node&& node, HybridTreePath<Indices...> tp)
176#endif
177 {
178 return Impl::child(std::forward<Node>(node),tp,std::index_sequence_for<Indices...>{});
179 }
180
181 template<typename Node, typename... Indices>
182#ifdef DOXYGEN
183 ImplementationDefined child (Node&& node, HybridTreePath<Indices...> treePath)
184#else
185 auto childStorage (Node&& node, HybridTreePath<Indices...> tp)
186#endif
187 {
188 static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty TreePath");
189 return Impl::childStorage(&node,tp,std::index_sequence_for<Indices...>{});
190 }
191
192
193#ifndef DOXYGEN
194
195 namespace impl {
196
197 template<typename T>
198 struct filter_void
199 {
200 using type = T;
201 };
202
203 template<>
204 struct filter_void<void>
205 {};
206
207 template<typename Node, std::size_t... indices>
208 struct _Child
209 : public filter_void<std::decay_t<decltype(child(std::declval<Node>(),index_constant<indices>{}...))>>
210 {};
211
212 }
213
214#endif // DOXYGEN
215
217
224 template<typename Node, std::size_t... indices>
225 using Child = typename impl::_Child<Node,indices...>::type;
226
227
228#ifndef DOXYGEN
229
230 namespace impl {
231
232 template<typename Node, typename TreePath>
233 struct _ChildForTreePath
234 {
235 using type = typename std::decay<decltype(child(std::declval<Node>(),std::declval<TreePath>()))>::type;
236 };
237
238 }
239
240#endif // DOXYGEN
241
243
251 template<typename Node, typename TreePath>
252 using ChildForTreePath = typename impl::_ChildForTreePath<Node,TreePath>::type;
253
254
255#ifndef DOXYGEN
256
257 namespace impl {
258
259 // By default, types are flat indices if they are integral
260 template<typename T>
261 struct _is_flat_index
262 {
263 using type = std::is_integral<T>;
264 };
265
266 // And so is any index_constant
267 template<std::size_t i>
268 struct _is_flat_index<index_constant<i>>
269 {
270 using type = std::true_type;
271 };
272
273 }
274
275#endif // DOXYGEN
276
278 /*
279 * This type trait can be used to check whether T is a flat index (i.e. either `std::size_t`
280 * or `index_constant`). The type trait normalizes T before doing the check, so it will also
281 * work correctly for references and cv-qualified types.
282 */
283 template<typename T>
284 using is_flat_index = typename impl::_is_flat_index<std::decay_t<T>>::type;
285
286#ifndef DOXYGEN
287
288 namespace impl {
289
290 // helper function for check in member child() functions that tolerates being passed something that
291 // isn't a TreePath. It will just return 0 in that case
292
293 template<typename T>
294 constexpr typename std::enable_if<
296 bool
297 >::type
298 _non_empty_tree_path (T)
299 {
300 return false;
301 }
302
303 template<typename T>
304 constexpr typename std::enable_if<
306 bool
307 >::type
308 _non_empty_tree_path (T t)
309 {
310 return treePathSize(t) > 0;
311 }
312
313 }
314
315#endif // DOXYGEN
316
318
319 } // namespace TypeTree
320} //namespace Dune
321
322#endif // DUNE_TYPETREE_CHILDEXTRACTION_HH
A hybrid version of TreePath that supports both compile time and run time indices.
Definition: treepath.hh:158
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:29
std::size_t degree(const Node &node)
Returns the degree of node as run time information.
Definition: nodeinterface.hh:79
constexpr std::size_t treePathSize(const HybridTreePath< T... > &)
Returns the size (number of components) of the given HybridTreePath.
Definition: treepath.hh:334
constexpr auto treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:326
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:284
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:225
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:252
ImplementationDefined child(Node &&node, HybridTreePath< Indices... > treePath)
Extracts the child of a node given by a HybridTreePath object.
Definition: childextraction.hh:173
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:50
Dune namespace.
Definition: alignedallocator.hh:13
This file implements several utilities related to std::shared_ptr.
Dummy struct used for documentation purposes.
Definition: documentation.hh:42
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 12, 23:30, 2024)