dune-typetree  2.8-git
childextraction.hh
Go to the documentation of this file.
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 
17 
18 
19 namespace 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
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 
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
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
ImplementationDefined childStorage(Node &&node, Indices... indices)
Definition: childextraction.hh:136
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
ImplementationDefined child(Node &&node, Indices... indices)
Extracts the child of a node given by a sequence of compile-time and run-time indices.
Definition: childextraction.hh:126
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
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
Definition: accumulate_static.hh:13
A hybrid version of TreePath that supports both compile time and run time indices.
Definition: treepath.hh:79