DUNE PDELab (2.7)

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 <utility>
8
13
14#include <dune/typetree/nodeinterface.hh>
15#include <dune/typetree/treepath.hh>
16
17
18namespace Dune {
19 namespace TypeTree {
20
25
26#ifndef DOXYGEN
27
28 namespace impl {
29
30 // ********************************************************************************
31 // end of the recursion, there are no child indices, so just return the node itself
32 // ********************************************************************************
33
34 struct IsPointerLike {
35 template <class Node>
36 auto require(const Node& node) -> decltype(*node);
37 };
38
39 template<typename Node>
40 auto child(Node&& node) -> decltype(std::forward<Node>(node))
41 {
42 return std::forward<Node>(node);
43 }
44
45 // for now, this wants the passed-in object to be pointer-like. I don't know how clever
46 // that is in the long run, though.
47 template<typename Node, typename std::enable_if_t<Dune::models<IsPointerLike,Node>(),int> = 0>
48 auto childStorage(Node&& node)
49 {
50 return std::forward<Node>(node);
51 }
52
53 // ********************************************************************************
54 // next index is a compile-time constant
55 // ********************************************************************************
56
57 // we need a concept to make sure that the node has a templated child()
58 // method
59 struct HasTemplateChildMethod {
60 template <class Node>
61 auto require(const Node& node) -> decltype(node.template child<0>());
62 };
63
64 // The actual implementation is rather simple, we just use an overload that requires the first index
65 // to be an index_constant, get the child and then recurse.
66 // It only gets ugly due to the enable_if, but without that trick, the error messages for the user
67 // can get *very* obscure (they are bad enough as it is).
68 template<typename Node, std::size_t i, typename... J,
69 typename std::enable_if<
70 Dune::models<HasTemplateChildMethod, Node>() &&
71 (i < StaticDegree<Node>::value), int>::type = 0>
72 decltype(auto) child(Node&& node, index_constant<i>, J... j)
73 {
74 return child(std::forward<Node>(node).template child<i>(),j...);
75 }
76
77 template<typename Node, std::size_t i, typename... J,
78 typename std::enable_if<
79 Dune::models<HasTemplateChildMethod, decltype(*std::declval<std::decay_t<Node>>())>() &&
80 (i < StaticDegree<decltype(*std::declval<Node>())>::value), int>::type = 0>
81 decltype(auto) childStorage(Node&& node, index_constant<i>, J... j)
82 {
83 return childStorage(std::forward<Node>(node)->template childStorage<i>(),j...);
84 }
85
86 // This overload is only present to give useful compiler
87 // error messages via static_assert in case the other overloads
88 // fail.
89 template<typename Node, std::size_t i, typename... J,
90 typename std::enable_if<
91 (!Dune::models<HasTemplateChildMethod, Node>()) ||
92 (i >= StaticDegree<Node>::value), int>::type = 0>
93 void child(Node&& node, index_constant<i>, J... j)
94 {
95 static_assert(Dune::models<HasTemplateChildMethod, Node>(), "Node does not have a template method child()");
96 static_assert(i < StaticDegree<Node>::value, "Child index out of range");
97 }
98
99 // ********************************************************************************
100 // next index is a run-time value
101 // ********************************************************************************
102
103 // The actual implemention here overloads on std::size_t. It is a little less ugly because it currently
104 // has a hard requirement on the PowerNode Tag (although only using is_convertible, as tags can be
105 // inherited (important!).
106 template<typename Node, typename... J>
107 decltype(auto)
108 child(
109 Node&& node,
110 std::enable_if_t<
111 std::is_convertible<
112 NodeTag<Node>,
113 PowerNodeTag
114 >{},
115 std::size_t> i,
116 J... j
117 )
118 {
119 return child(std::forward<Node>(node).child(i),j...);
120 }
121
122 template<typename Node, typename... J>
123 decltype(auto)
124 childStorage(
125 Node&& node,
126 std::enable_if_t<
127 std::is_convertible<
128 NodeTag<decltype(*std::declval<Node>())>,
129 PowerNodeTag
130 >{},
131 std::size_t> i,
132 J... j
133 )
134 {
135 return childStorage(std::forward<Node>(node)->childStorage(i),j...);
136 }
137
138 template<typename Node, typename... Indices, std::size_t... i>
139 decltype(auto) child(Node&& node, HybridTreePath<Indices...> tp, std::index_sequence<i...>)
140 {
141 return child(std::forward<Node>(node),treePathEntry<i>(tp)...);
142 }
143
144 template<typename Node, typename... Indices, std::size_t... i>
145 decltype(auto) childStorage(Node&& node, HybridTreePath<Indices...> tp, std::index_sequence<i...>)
146 {
147 return childStorage(std::forward<Node>(node),treePathEntry<i>(tp)...);
148 }
149
150 } // namespace imp
151
152#endif // DOXYGEN
153
155
177 template<typename Node, typename... Indices>
178#ifdef DOXYGEN
179 ImplementationDefined child(Node&& node, Indices... indices)
180#else
181 decltype(auto) child(Node&& node, Indices... indices)
182#endif
183 {
184 return impl::child(std::forward<Node>(node),indices...);
185 }
186
187 template<typename Node, typename... Indices>
188#ifdef DOXYGEN
189 ImplementationDefined childStorage(Node&& node, Indices... indices)
190#else
191 auto childStorage(Node&& node, Indices... indices)
192#endif
193 {
194 //static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty list of child indices");
195 return impl::childStorage(&node,indices...);
196 }
197
199
222 template<typename Node, typename... Indices>
223#ifdef DOXYGEN
225#else
226 decltype(auto) child(Node&& node, HybridTreePath<Indices...> tp)
227#endif
228 {
229 return impl::child(std::forward<Node>(node),tp,std::index_sequence_for<Indices...>{});
230 }
231
232 template<typename Node, typename... Indices>
233#ifdef DOXYGEN
234 ImplementationDefined child(Node&& node, HybridTreePath<Indices...> treePath)
235#else
236 auto childStorage(Node&& node, HybridTreePath<Indices...> tp)
237#endif
238 {
239 static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty TreePath");
240 return impl::childStorage(&node,tp,std::index_sequence_for<Indices...>{});
241 }
242
243
244#ifndef DOXYGEN
245
246 namespace impl {
247
248 template<typename T>
249 struct filter_void
250 {
251 using type = T;
252 };
253
254 template<>
255 struct filter_void<void>
256 {};
257
258 template<typename Node, std::size_t... indices>
259 struct _Child
260 : public filter_void<std::decay_t<decltype(child(std::declval<Node>(),index_constant<indices>{}...))>>
261 {};
262
263 }
264
265#endif // DOXYGEN
266
268
275 template<typename Node, std::size_t... indices>
276 using Child = typename impl::_Child<Node,indices...>::type;
277
278
279#ifndef DOXYGEN
280
281 namespace impl {
282
283 template<typename Node, typename TreePath>
284 struct _ChildForTreePath
285 {
286 using type = typename std::decay<decltype(child(std::declval<Node>(),std::declval<TreePath>()))>::type;
287 };
288
289 }
290
291#endif // DOXYGEN
292
294
302 template<typename Node, typename TreePath>
303 using ChildForTreePath = typename impl::_ChildForTreePath<Node,TreePath>::type;
304
305
306#ifndef DOXYGEN
307
308 namespace impl {
309
310 // By default, types are flat indices if they are integral
311 template<typename T>
312 struct _is_flat_index
313 {
314 using type = std::is_integral<T>;
315 };
316
317 // And so is any index_constant
318 template<std::size_t i>
319 struct _is_flat_index<index_constant<i>>
320 {
321 using type = std::true_type;
322 };
323
324 }
325
326#endif // DOXYGEN
327
329 /*
330 * This type trait can be used to check whether T is a flat index (i.e. either `std::size_t`
331 * or `index_constant`). The type trait normalizes T before doing the check, so it will also
332 * work correctly for references and cv-qualified types.
333 */
334 template<typename T>
335 using is_flat_index = typename impl::_is_flat_index<std::decay_t<T>>::type;
336
337#ifndef DOXYGEN
338
339 namespace impl {
340
341 // helper function for check in member child() functions that tolerates being passed something that
342 // isn't a TreePath. It will just return 0 in that case
343
344 template<typename T>
345 constexpr typename std::enable_if<
347 bool
348 >::type
349 _non_empty_tree_path(T)
350 {
351 return false;
352 }
353
354 template<typename T>
355 constexpr typename std::enable_if<
357 bool
358 >::type
359 _non_empty_tree_path(T t)
360 {
361 return treePathSize(t) > 0;
362 }
363
364 }
365
366#endif // DOXYGEN
367
369
370 } // namespace TypeTree
371} //namespace Dune
372
373#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
constexpr auto models()
Check if concept is modeled by given types.
Definition: concept.hh:182
typename std::decay_t< Node >::NodeTag NodeTag
Returns the node tag of the given Node.
Definition: nodeinterface.hh:62
std::integral_constant< std::size_t, degree(static_cast< std::decay_t< Node > * >(nullptr), NodeTag< std::decay_t< Node > >()) > StaticDegree
Returns the statically known degree of the given Node type as a std::integral_constant.
Definition: nodeinterface.hh:105
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:335
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:276
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:303
ImplementationDefined child(Node &&node, HybridTreePath< Indices... > treePath)
Extracts the child of a node given by a HybridTreePath object.
Definition: childextraction.hh:224
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:49
Dune namespace.
Definition: alignedallocator.hh:14
This file implements the class shared_ptr (a reference counting pointer), for those systems that don'...
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 (Jul 15, 22:36, 2024)