Dune Core Modules (2.9.0)

powernode.hh
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifndef DUNE_TYPETREE_POWERNODE_HH
5 #define DUNE_TYPETREE_POWERNODE_HH
6 
7 #include <cassert>
8 #include <array>
9 #include <memory>
10 #include <type_traits>
11 
13 #include <dune/common/std/type_traits.hh>
14 
15 #include <dune/typetree/nodetags.hh>
16 #include <dune/typetree/utility.hh>
17 #include <dune/typetree/childextraction.hh>
18 #include <dune/typetree/typetraits.hh>
19 
20 namespace Dune {
21  namespace TypeTree {
22 
29 #ifndef DOXYGEN
30 
32  template<typename PowerNode, typename T, std::size_t k>
33  struct AssertPowerNodeChildCount
34  : public std::enable_if<std::is_same<
35  typename PowerNode::ChildType,
36  T>::value &&
37  PowerNode::degree() == k,
38  T>
39  {};
40 
41 #endif
42 
48  template<typename T, std::size_t k>
49  class PowerNode
50  {
51 
52  public:
53 
55  static const bool isLeaf = false;
56 
58  static const bool isPower = true;
59 
61  static const bool isComposite = false;
62 
64  [[deprecated("Will be removed after release 2.9. Use degree()")]]
65  static const std::size_t CHILDREN = k;
66 
67  static constexpr auto degree ()
68  {
69  return std::integral_constant<std::size_t,k>{};
70  }
71 
74 
76  typedef T ChildType;
77 
79  typedef std::array<std::shared_ptr<T>,k> NodeStorage;
80 
81 
83  template<std::size_t i>
84  struct Child
85  {
86 
87  static_assert((i < degree()), "child index out of range");
88 
90  typedef T Type;
91 
93  typedef T type;
94  };
95 
98 
100 
103  template<std::size_t i>
104  T& child (index_constant<i> = {})
105  {
106  static_assert((i < degree()), "child index out of range");
107  return *_children[i];
108  }
109 
111 
114  template<std::size_t i>
115  const T& child (index_constant<i> = {}) const
116  {
117  static_assert((i < degree()), "child index out of range");
118  return *_children[i];
119  }
120 
122 
125  template<std::size_t i>
126  std::shared_ptr<T> childStorage (index_constant<i> = {})
127  {
128  static_assert((i < degree()), "child index out of range");
129  return _children[i];
130  }
131 
133 
136  template<std::size_t i>
137  std::shared_ptr<const T> childStorage (index_constant<i> = {}) const
138  {
139  static_assert((i < degree()), "child index out of range");
140  return _children[i];
141  }
142 
144  template<std::size_t i>
145  void setChild (T& t, index_constant<i> = {})
146  {
147  static_assert((i < degree()), "child index out of range");
148  _children[i] = stackobject_to_shared_ptr(t);
149  }
150 
152  template<std::size_t i>
153  void setChild (T&& t, index_constant<i> = {})
154  {
155  static_assert((i < degree()), "child index out of range");
156  _children[i] = convert_arg(std::move(t));
157  }
158 
160  template<std::size_t i>
161  void setChild (std::shared_ptr<T> st, index_constant<i> = {})
162  {
163  static_assert((i < degree()), "child index out of range");
164  _children[i] = std::move(st);
165  }
166 
168 
169 
172 
174 
177  T& child (std::size_t i)
178  {
179  assert(i < degree() && "child index out of range");
180  return *_children[i];
181  }
182 
184 
187  const T& child (std::size_t i) const
188  {
189  assert(i < degree() && "child index out of range");
190  return *_children[i];
191  }
192 
194 
197  std::shared_ptr<T> childStorage (std::size_t i)
198  {
199  assert(i < degree() && "child index out of range");
200  return _children[i];
201  }
202 
204 
207  std::shared_ptr<const T> childStorage (std::size_t i) const
208  {
209  assert(i < degree() && "child index out of range");
210  return _children[i];
211  }
212 
214  void setChild (std::size_t i, T& t)
215  {
216  assert(i < degree() && "child index out of range");
217  _children[i] = stackobject_to_shared_ptr(t);
218  }
219 
221  void setChild (std::size_t i, T&& t)
222  {
223  assert(i < degree() && "child index out of range");
224  _children[i] = convert_arg(std::move(t));
225  }
226 
228  void setChild (std::size_t i, std::shared_ptr<T> st)
229  {
230  assert(i < degree() && "child index out of range");
231  _children[i] = std::move(st);
232  }
233 
234  const NodeStorage& nodeStorage () const
235  {
236  return _children;
237  }
238 
240 
243 
244  // The following two methods require a little bit of SFINAE trickery to work correctly:
245  // We have to make sure that they don't shadow the methods for direct child access because
246  // those get called by the generic child() machinery. If that machinery picks up the methods
247  // defined below, we have an infinite recursion.
248  // So the methods make sure that either
249  //
250  // * there are more than one argument. In that case, we got multiple indices and can forward
251  // to the general machine.
252  //
253  // * the first argument is not a valid flat index, i.e. either a std::size_t or an index_constant.
254  // The argument thus has to be some kind of TreePath instance that we can also pass to the
255  // generic machine.
256  //
257  // The above SFINAE logic works, but there is still a problem with the return type deduction.
258  // We have to do a lazy lookup of the return type after SFINAE has succeeded, otherwise the return
259  // type deduction will trigger the infinite recursion.
260 
262 
266 #ifdef DOXYGEN
267  template<typename... Indices>
269 #else
270  template<typename I0, typename... I,
271  std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
272  decltype(auto) child (I0 i0, I... i)
273 #endif
274  {
275  static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
276  "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
277  );
278  return Dune::TypeTree::child(*this,i0,i...);
279  }
280 
282 
286 #ifdef DOXYGEN
287  template<typename... Indices>
288  const ImplementationDefined& child (Indices... indices)
289 #else
290  template<typename I0, typename... I,
291  std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
292  decltype(auto) child (I0 i0, I... i) const
293 #endif
294  {
295  static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
296  "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
297  );
298  return Dune::TypeTree::child(*this,i0,i...);
299  }
300 
302 
305 
306  protected:
307 
309 
318  {}
319 
321  explicit PowerNode (const NodeStorage& children)
322  : _children(children)
323  {}
324 
326  explicit PowerNode (T& t, bool distinct_objects = true)
327  {
328  if (distinct_objects)
329  {
330  for (typename NodeStorage::iterator it = _children.begin(); it != _children.end(); ++it)
331  *it = std::make_shared<T>(t);
332  }
333  else
334  {
335  std::shared_ptr<T> sp = stackobject_to_shared_ptr(t);
336  std::fill(_children.begin(),_children.end(),sp);
337  }
338  }
339 
340 #ifdef DOXYGEN
341 
343  PowerNode(T& t1, T& t2, ...)
344  {}
345 
346 #else
347 
348  template<typename... Children,
349  std::enable_if_t<
350  std::conjunction<std::is_same<ChildType, std::decay_t<Children>>...>::value
351  ,int> = 0>
352  PowerNode (Children&&... children)
353  {
354  static_assert(degree() == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
355  _children = NodeStorage{convert_arg(std::forward<Children>(children))...};
356  }
357 
358  template<typename... Children,
359  std::enable_if_t<
360  std::conjunction<std::is_same<ChildType, Children>...>::value
361  ,int> = 0>
362  PowerNode (std::shared_ptr<Children>... children)
363  {
364  static_assert(degree() == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
365  _children = NodeStorage{children...};
366  }
367 
368 #endif // DOXYGEN
369 
371 
372  private:
373  NodeStorage _children;
374  };
375 
377 
378  } // namespace TypeTree
379 } //namespace Dune
380 
381 #endif // DUNE_TYPETREE_POWERNODE_HH
Collect k instances of type T within a dune-typetree.
Definition: powernode.hh:50
void setChild(T &t, index_constant< i >={})
Sets the i-th child to the passed-in value.
Definition: powernode.hh:145
ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:268
const T & child(std::size_t i) const
Returns the i-th child (const version).
Definition: powernode.hh:187
void setChild(std::shared_ptr< T > st, index_constant< i >={})
Sets the stored value representing the i-th child to the passed-in value.
Definition: powernode.hh:161
PowerNode(T &t1, T &t2,...)
Initialize all children with the passed-in objects.
Definition: powernode.hh:343
const ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:288
std::shared_ptr< T > childStorage(index_constant< i >={})
Returns the storage of the i-th child.
Definition: powernode.hh:126
std::array< std::shared_ptr< T >, k > NodeStorage
The type used for storing the children.
Definition: powernode.hh:79
std::shared_ptr< const T > childStorage(index_constant< i >={}) const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:137
PowerNode(T &t, bool distinct_objects=true)
Initialize all children with copies of a storage object constructed from the parameter t.
Definition: powernode.hh:326
PowerNodeTag NodeTag
The type tag that describes a PowerNode.
Definition: powernode.hh:73
static const std::size_t CHILDREN
The number of children.
Definition: powernode.hh:65
void setChild(std::size_t i, std::shared_ptr< T > st)
Sets the stored value representing the i-th child to the passed-in value.
Definition: powernode.hh:228
static const bool isComposite
Mark this class as a non composite in the dune-typetree.
Definition: powernode.hh:61
std::shared_ptr< const T > childStorage(std::size_t i) const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:207
static const bool isLeaf
Mark this class as non leaf in the dune-typetree.
Definition: powernode.hh:55
T & child(index_constant< i >={})
Returns the i-th child.
Definition: powernode.hh:104
static const bool isPower
Mark this class as a power in the dune-typetree.
Definition: powernode.hh:58
PowerNode(const NodeStorage &children)
Initialize the PowerNode with a copy of the passed-in storage type.
Definition: powernode.hh:321
T ChildType
The type of each child.
Definition: powernode.hh:76
T & child(std::size_t i)
Returns the i-th child.
Definition: powernode.hh:177
void setChild(std::size_t i, T &&t)
Store the passed value in i-th child.
Definition: powernode.hh:221
void setChild(T &&t, index_constant< i >={})
Store the passed value in i-th child.
Definition: powernode.hh:153
std::shared_ptr< T > childStorage(std::size_t i)
Returns the storage of the i-th child.
Definition: powernode.hh:197
const T & child(index_constant< i >={}) const
Returns the i-th child (const version).
Definition: powernode.hh:115
PowerNode()
Default constructor.
Definition: powernode.hh:317
void setChild(std::size_t i, T &t)
Sets the i-th child to the passed-in value.
Definition: powernode.hh:214
Traits for type conversions and type information.
std::size_t degree(const Node &node)
Returns the degree of node as run time information.
Definition: nodeinterface.hh:85
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
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:51
Dune namespace.
Definition: alignedallocator.hh:13
std::shared_ptr< T > stackobject_to_shared_ptr(T &t)
Create a shared_ptr for a stack-allocated object.
Definition: shared_ptr.hh:72
Dummy struct used for documentation purposes.
Definition: documentation.hh:42
Check if type represents a tree path.
Definition: typetraits.hh:182
Tag designating a power node.
Definition: nodetags.hh:19
Access to the type and storage type of the i-th child.
Definition: powernode.hh:85
T type
The type of the child.
Definition: powernode.hh:93
T Type
The type of the child.
Definition: powernode.hh:87
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 6, 22:30, 2024)