DUNE PDELab (git)

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 // 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_POWERNODE_HH
7 #define DUNE_TYPETREE_POWERNODE_HH
8 
9 #include <cassert>
10 #include <array>
11 #include <memory>
12 #include <type_traits>
13 
15 #include <dune/common/std/type_traits.hh>
16 
17 #include <dune/typetree/nodetags.hh>
18 #include <dune/typetree/utility.hh>
19 #include <dune/typetree/childextraction.hh>
20 #include <dune/typetree/typetraits.hh>
21 
22 namespace Dune {
23  namespace TypeTree {
24 
31 #ifndef DOXYGEN
32 
34  template<typename PowerNode, typename T, std::size_t k>
35  struct AssertPowerNodeChildCount
36  : public std::enable_if<std::is_same<
37  typename PowerNode::ChildType,
38  T>::value &&
39  PowerNode::degree() == k,
40  T>
41  {};
42 
43 #endif
44 
50  template<typename T, std::size_t k>
51  class PowerNode
52  {
53 
54  public:
55 
57  static const bool isLeaf = false;
58 
60  static const bool isPower = true;
61 
63  static const bool isComposite = false;
64 
65  static constexpr auto degree ()
66  {
67  return std::integral_constant<std::size_t,k>{};
68  }
69 
72 
74  typedef T ChildType;
75 
77  typedef std::array<std::shared_ptr<T>,k> NodeStorage;
78 
79 
81  template<std::size_t i>
82  struct Child
83  {
84 
85  static_assert((i < degree()), "child index out of range");
86 
88  typedef T Type;
89 
91  typedef T type;
92  };
93 
96 
98 
101  template<std::size_t i>
102  T& child (index_constant<i> = {})
103  {
104  static_assert((i < degree()), "child index out of range");
105  return *_children[i];
106  }
107 
109 
112  template<std::size_t i>
113  const T& child (index_constant<i> = {}) const
114  {
115  static_assert((i < degree()), "child index out of range");
116  return *_children[i];
117  }
118 
120 
123  template<std::size_t i>
124  std::shared_ptr<T> childStorage (index_constant<i> = {})
125  {
126  static_assert((i < degree()), "child index out of range");
127  return _children[i];
128  }
129 
131 
134  template<std::size_t i>
135  std::shared_ptr<const T> childStorage (index_constant<i> = {}) const
136  {
137  static_assert((i < degree()), "child index out of range");
138  return _children[i];
139  }
140 
142  template<std::size_t i>
143  void setChild (T& t, index_constant<i> = {})
144  {
145  static_assert((i < degree()), "child index out of range");
146  _children[i] = stackobject_to_shared_ptr(t);
147  }
148 
150  template<std::size_t i>
151  void setChild (T&& t, index_constant<i> = {})
152  {
153  static_assert((i < degree()), "child index out of range");
154  _children[i] = convert_arg(std::move(t));
155  }
156 
158  template<std::size_t i>
159  void setChild (std::shared_ptr<T> st, index_constant<i> = {})
160  {
161  static_assert((i < degree()), "child index out of range");
162  _children[i] = std::move(st);
163  }
164 
166 
167 
170 
172 
175  T& child (std::size_t i)
176  {
177  assert(i < degree() && "child index out of range");
178  return *_children[i];
179  }
180 
182 
185  const T& child (std::size_t i) const
186  {
187  assert(i < degree() && "child index out of range");
188  return *_children[i];
189  }
190 
192 
195  std::shared_ptr<T> childStorage (std::size_t i)
196  {
197  assert(i < degree() && "child index out of range");
198  return _children[i];
199  }
200 
202 
205  std::shared_ptr<const T> childStorage (std::size_t i) const
206  {
207  assert(i < degree() && "child index out of range");
208  return _children[i];
209  }
210 
212  void setChild (std::size_t i, T& t)
213  {
214  assert(i < degree() && "child index out of range");
215  _children[i] = stackobject_to_shared_ptr(t);
216  }
217 
219  void setChild (std::size_t i, T&& t)
220  {
221  assert(i < degree() && "child index out of range");
222  _children[i] = convert_arg(std::move(t));
223  }
224 
226  void setChild (std::size_t i, std::shared_ptr<T> st)
227  {
228  assert(i < degree() && "child index out of range");
229  _children[i] = std::move(st);
230  }
231 
232  const NodeStorage& nodeStorage () const
233  {
234  return _children;
235  }
236 
238 
241 
242  // The following two methods require a little bit of SFINAE trickery to work correctly:
243  // We have to make sure that they don't shadow the methods for direct child access because
244  // those get called by the generic child() machinery. If that machinery picks up the methods
245  // defined below, we have an infinite recursion.
246  // So the methods make sure that either
247  //
248  // * there are more than one argument. In that case, we got multiple indices and can forward
249  // to the general machine.
250  //
251  // * the first argument is not a valid flat index, i.e. either a std::size_t or an index_constant.
252  // The argument thus has to be some kind of TreePath instance that we can also pass to the
253  // generic machine.
254  //
255  // The above SFINAE logic works, but there is still a problem with the return type deduction.
256  // We have to do a lazy lookup of the return type after SFINAE has succeeded, otherwise the return
257  // type deduction will trigger the infinite recursion.
258 
260 
264 #ifdef DOXYGEN
265  template<typename... Indices>
267 #else
268  template<typename I0, typename... I,
269  std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
270  decltype(auto) child (I0 i0, I... i)
271 #endif
272  {
273  static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
274  "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
275  );
276  return Dune::TypeTree::child(*this,i0,i...);
277  }
278 
280 
284 #ifdef DOXYGEN
285  template<typename... Indices>
286  const ImplementationDefined& child (Indices... indices)
287 #else
288  template<typename I0, typename... I,
289  std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
290  decltype(auto) child (I0 i0, I... i) const
291 #endif
292  {
293  static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
294  "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
295  );
296  return Dune::TypeTree::child(*this,i0,i...);
297  }
298 
300 
303 
304  protected:
305 
307 
316  {}
317 
319  explicit PowerNode (const NodeStorage& children)
320  : _children(children)
321  {}
322 
324  explicit PowerNode (T& t, bool distinct_objects = true)
325  {
326  if (distinct_objects)
327  {
328  for (typename NodeStorage::iterator it = _children.begin(); it != _children.end(); ++it)
329  *it = std::make_shared<T>(t);
330  }
331  else
332  {
333  std::shared_ptr<T> sp = stackobject_to_shared_ptr(t);
334  std::fill(_children.begin(),_children.end(),sp);
335  }
336  }
337 
338 #ifdef DOXYGEN
339 
341  PowerNode(T& t1, T& t2, ...)
342  {}
343 
344 #else
345 
346  template<typename... Children,
347  std::enable_if_t<
348  std::conjunction<std::is_same<ChildType, std::decay_t<Children>>...>::value
349  ,int> = 0>
350  PowerNode (Children&&... children)
351  {
352  static_assert(degree() == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
353  _children = NodeStorage{convert_arg(std::forward<Children>(children))...};
354  }
355 
356  template<typename... Children,
357  std::enable_if_t<
358  std::conjunction<std::is_same<ChildType, Children>...>::value
359  ,int> = 0>
360  PowerNode (std::shared_ptr<Children>... children)
361  {
362  static_assert(degree() == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
363  _children = NodeStorage{children...};
364  }
365 
366 #endif // DOXYGEN
367 
369 
370  private:
371  NodeStorage _children;
372  };
373 
375 
376  } // namespace TypeTree
377 } //namespace Dune
378 
379 #endif // DUNE_TYPETREE_POWERNODE_HH
Collect k instances of type T within a dune-typetree.
Definition: powernode.hh:52
void setChild(T &t, index_constant< i >={})
Sets the i-th child to the passed-in value.
Definition: powernode.hh:143
ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:266
const T & child(std::size_t i) const
Returns the i-th child (const version).
Definition: powernode.hh:185
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:159
PowerNode(T &t1, T &t2,...)
Initialize all children with the passed-in objects.
Definition: powernode.hh:341
const ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:286
std::shared_ptr< T > childStorage(index_constant< i >={})
Returns the storage of the i-th child.
Definition: powernode.hh:124
std::array< std::shared_ptr< T >, k > NodeStorage
The type used for storing the children.
Definition: powernode.hh:77
std::shared_ptr< const T > childStorage(index_constant< i >={}) const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:135
PowerNode(T &t, bool distinct_objects=true)
Initialize all children with copies of a storage object constructed from the parameter t.
Definition: powernode.hh:324
PowerNodeTag NodeTag
The type tag that describes a PowerNode.
Definition: powernode.hh:71
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:226
static const bool isComposite
Mark this class as a non composite in the dune-typetree.
Definition: powernode.hh:63
std::shared_ptr< const T > childStorage(std::size_t i) const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:205
static const bool isLeaf
Mark this class as non leaf in the dune-typetree.
Definition: powernode.hh:57
T & child(index_constant< i >={})
Returns the i-th child.
Definition: powernode.hh:102
static const bool isPower
Mark this class as a power in the dune-typetree.
Definition: powernode.hh:60
PowerNode(const NodeStorage &children)
Initialize the PowerNode with a copy of the passed-in storage type.
Definition: powernode.hh:319
T ChildType
The type of each child.
Definition: powernode.hh:74
T & child(std::size_t i)
Returns the i-th child.
Definition: powernode.hh:175
void setChild(std::size_t i, T &&t)
Store the passed value in i-th child.
Definition: powernode.hh:219
void setChild(T &&t, index_constant< i >={})
Store the passed value in i-th child.
Definition: powernode.hh:151
std::shared_ptr< T > childStorage(std::size_t i)
Returns the storage of the i-th child.
Definition: powernode.hh:195
const T & child(index_constant< i >={}) const
Returns the i-th child (const version).
Definition: powernode.hh:113
PowerNode()
Default constructor.
Definition: powernode.hh:315
void setChild(std::size_t i, T &t)
Sets the i-th child to the passed-in value.
Definition: powernode.hh:212
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:79
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:128
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:50
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:184
Tag designating a power node.
Definition: nodetags.hh:21
Access to the type and storage type of the i-th child.
Definition: powernode.hh:83
T type
The type of the child.
Definition: powernode.hh:91
T Type
The type of the child.
Definition: powernode.hh:85
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)