dune-typetree  2.7.1
powernode.hh
Go to the documentation of this file.
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 
12 #include <dune/common/typetraits.hh>
13 #include <dune/common/std/type_traits.hh>
14 
16 #include <dune/typetree/utility.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::CHILDREN == 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  static const std::size_t CHILDREN = k;
65 
66  static constexpr std::size_t degree()
67  {
68  return k;
69  }
70 
73 
75  typedef T ChildType;
76 
78  typedef std::shared_ptr<T> ChildStorageType;
79 
81  typedef std::shared_ptr<const T> ChildConstStorageType;
82 
84  typedef std::array<ChildStorageType,k> NodeStorage;
85 
86 
88  template<std::size_t i>
89  struct Child
90  {
91 
92  static_assert((i < CHILDREN), "child index out of range");
93 
95  typedef T Type;
96 
98  typedef T type;
99 
102 
105  };
106 
109 
111 
114  template<std::size_t i>
115  T& child (index_constant<i> = {})
116  {
117  static_assert((i < CHILDREN), "child index out of range");
118  return *_children[i];
119  }
120 
122 
125  template<std::size_t i>
126  const T& child (index_constant<i> = {}) const
127  {
128  static_assert((i < CHILDREN), "child index out of range");
129  return *_children[i];
130  }
131 
133 
136  template<std::size_t i>
137  ChildStorageType childStorage(index_constant<i> = {})
138  {
139  static_assert((i < CHILDREN), "child index out of range");
140  return _children[i];
141  }
142 
144 
150  template<std::size_t i>
151  ChildConstStorageType childStorage(index_constant<i> = {}) const
152  {
153  static_assert((i < CHILDREN), "child index out of range");
154  return _children[i];
155  }
156 
158  template<std::size_t i>
159  void setChild (T& t, index_constant<i> = {})
160  {
161  static_assert((i < CHILDREN), "child index out of range");
162  _children[i] = stackobject_to_shared_ptr(t);
163  }
164 
166  template<std::size_t i>
167  void setChild(T&& t, index_constant<i> = {})
168  {
169  static_assert((i < CHILDREN), "child index out of range");
170  _children[i] = convert_arg(std::move(t));
171  }
172 
174  template<std::size_t i>
175  void setChild (ChildStorageType st, index_constant<i> = {})
176  {
177  static_assert((i < CHILDREN), "child index out of range");
178  _children[i] = st;
179  }
180 
182 
183 
186 
188 
191  T& child (std::size_t i)
192  {
193  assert(i < CHILDREN && "child index out of range");
194  return *_children[i];
195  }
196 
198 
201  const T& child (std::size_t i) const
202  {
203  assert(i < CHILDREN && "child index out of range");
204  return *_children[i];
205  }
206 
208 
212  {
213  assert(i < CHILDREN && "child index out of range");
214  return _children[i];
215  }
216 
218 
224  ChildConstStorageType childStorage (std::size_t i) const
225  {
226  assert(i < CHILDREN && "child index out of range");
227  return (_children[i]);
228  }
229 
231  void setChild (std::size_t i, T& t)
232  {
233  assert(i < CHILDREN && "child index out of range");
234  _children[i] = stackobject_to_shared_ptr(t);
235  }
236 
238  void setChild(std::size_t i, T&& t)
239  {
240  assert(i < CHILDREN && "child index out of range");
241  _children[i] = convert_arg(std::move(t));
242  }
243 
245  void setChild (std::size_t i, ChildStorageType st)
246  {
247  assert(i < CHILDREN && "child index out of range");
248  _children[i] = st;
249  }
250 
251  const NodeStorage& nodeStorage() const
252  {
253  return _children;
254  }
255 
257 
260 
261  // The following two methods require a little bit of SFINAE trickery to work correctly:
262  // We have to make sure that they don't shadow the methods for direct child access because
263  // those get called by the generic child() machinery. If that machinery picks up the methods
264  // defined below, we have an infinite recursion.
265  // So the methods make sure that either
266  //
267  // * there are more than one argument. In that case, we got multiple indices and can forward
268  // to the general machine.
269  //
270  // * the first argument is not a valid flat index, i.e. either a std::size_t or an index_constant.
271  // The argument thus has to be some kind of TreePath instance that we can also pass to the
272  // generic machine.
273  //
274  // The above SFINAE logic works, but there is still a problem with the return type deduction.
275  // We have to do a lazy lookup of the return type after SFINAE has succeeded, otherwise the return
276  // type deduction will trigger the infinite recursion.
277 
279 
283 #ifdef DOXYGEN
284  template<typename... Indices>
285  ImplementationDefined& child(Indices... indices)
286 #else
287  template<typename I0, typename... I,
288  std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
289  decltype(auto) child(I0 i0, I... i)
290 #endif
291  {
292  static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
293  "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
294  );
295  return Dune::TypeTree::child(*this,i0,i...);
296  }
297 
299 
303 #ifdef DOXYGEN
304  template<typename... Indices>
305  const ImplementationDefined& child(Indices... indices)
306 #else
307  template<typename I0, typename... I,
308  std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
309  decltype(auto) child(I0 i0, I... i) const
310 #endif
311  {
312  static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
313  "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
314  );
315  return Dune::TypeTree::child(*this,i0,i...);
316  }
317 
319 
322 
323  protected:
324 
326 
335  {}
336 
338  explicit PowerNode(const NodeStorage& children)
339  : _children(children)
340  {}
341 
343  explicit PowerNode (T& t, bool distinct_objects = true)
344  {
345  if (distinct_objects)
346  {
347  for (typename NodeStorage::iterator it = _children.begin(); it != _children.end(); ++it)
348  *it = std::make_shared<T>(t);
349  }
350  else
351  {
352  std::shared_ptr<T> sp = stackobject_to_shared_ptr(t);
353  std::fill(_children.begin(),_children.end(),sp);
354  }
355  }
356 
357 #ifdef DOXYGEN
358 
360  PowerNode(T& t1, T& t2, ...)
361  {}
362 
363 #else
364 
365  template<typename... Children,
366  std::enable_if_t<
367  Dune::Std::conjunction<std::is_same<ChildType, std::decay_t<Children>>...>::value
368  ,int> = 0>
369  PowerNode (Children&&... children)
370  {
371  static_assert(CHILDREN == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
372  _children = NodeStorage{convert_arg(std::forward<Children>(children))...};
373  }
374 
375  template<typename... Children,
376  std::enable_if_t<
377  Dune::Std::conjunction<std::is_same<ChildType, Children>...>::value
378  ,int> = 0>
379  PowerNode (std::shared_ptr<Children>... children)
380  {
381  static_assert(CHILDREN == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
382  _children = NodeStorage{children...};
383  }
384 
385 #endif // DOXYGEN
386 
388 
389  private:
390  NodeStorage _children;
391  };
392 
394 
395  } // namespace TypeTree
396 } //namespace Dune
397 
398 #endif // DUNE_TYPETREE_POWERNODE_HH
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:179
Definition: accumulate_static.hh:13
Tag designating a power node.
Definition: nodetags.hh:19
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:159
ChildStorageType childStorage(std::size_t i)
Returns the storage of the i-th child.
Definition: powernode.hh:211
ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:285
const T & child(std::size_t i) const
Returns the i-th child (const version).
Definition: powernode.hh:201
PowerNode(T &t1, T &t2,...)
Initialize all children with the passed-in objects.
Definition: powernode.hh:360
const ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:305
ChildConstStorageType childStorage(std::size_t i) const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:224
void setChild(std::size_t i, ChildStorageType st)
Sets the stored value representing the i-th child to the passed-in value.
Definition: powernode.hh:245
PowerNode(T &t, bool distinct_objects=true)
Initialize all children with copies of a storage object constructed from the parameter t.
Definition: powernode.hh:343
PowerNodeTag NodeTag
The type tag that describes a PowerNode.
Definition: powernode.hh:72
std::array< ChildStorageType, k > NodeStorage
The type used for storing the children.
Definition: powernode.hh:84
static const std::size_t CHILDREN
The number of children.
Definition: powernode.hh:64
const NodeStorage & nodeStorage() const
Definition: powernode.hh:251
static const bool isComposite
Mark this class as a non composite in the dune-typetree.
Definition: powernode.hh:61
std::shared_ptr< T > ChildStorageType
The storage type of each child.
Definition: powernode.hh:78
static constexpr std::size_t degree()
Definition: powernode.hh:66
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:115
static const bool isPower
Mark this class as a power in the dune-typetree.
Definition: powernode.hh:58
void setChild(ChildStorageType st, index_constant< i >={})
Sets the stored value representing the i-th child to the passed-in value.
Definition: powernode.hh:175
PowerNode(const NodeStorage &children)
Initialize the PowerNode with a copy of the passed-in storage type.
Definition: powernode.hh:338
T ChildType
The type of each child.
Definition: powernode.hh:75
ChildConstStorageType childStorage(index_constant< i >={}) const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:151
T & child(std::size_t i)
Returns the i-th child.
Definition: powernode.hh:191
void setChild(std::size_t i, T &&t)
Store the passed value in i-th child.
Definition: powernode.hh:238
void setChild(T &&t, index_constant< i >={})
Store the passed value in i-th child.
Definition: powernode.hh:167
const T & child(index_constant< i >={}) const
Returns the i-th child (const version).
Definition: powernode.hh:126
ChildStorageType childStorage(index_constant< i >={})
Returns the storage of the i-th child.
Definition: powernode.hh:137
std::shared_ptr< const T > ChildConstStorageType
The const version of the storage type of each child.
Definition: powernode.hh:81
PowerNode()
Default constructor.
Definition: powernode.hh:334
void setChild(std::size_t i, T &t)
Sets the i-th child to the passed-in value.
Definition: powernode.hh:231
Access to the type and storage type of the i-th child.
Definition: powernode.hh:90
T type
The type of the child.
Definition: powernode.hh:98
T Type
The type of the child.
Definition: powernode.hh:92
ChildStorageType Storage
The storage type of the child.
Definition: powernode.hh:101
ChildConstStorageType ConstStorage
The const storage type of the child.
Definition: powernode.hh:104
Check if type represents a tree path.
Definition: typetraits.hh:190