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
20namespace 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>
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>
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
T & child(std::size_t i)
Returns the i-th child.
Definition: powernode.hh:177
const T & child(index_constant< i >={}) const
Returns the i-th child (const version).
Definition: powernode.hh:115
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
std::shared_ptr< T > childStorage(index_constant< i >={})
Returns the storage of the i-th child.
Definition: powernode.hh:126
PowerNode(T &t1, T &t2,...)
Initialize all children with the passed-in objects.
Definition: powernode.hh:343
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
const T & child(std::size_t i) const
Returns the i-th child (const version).
Definition: powernode.hh:187
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 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
static const bool isLeaf
Mark this class as non leaf in the dune-typetree.
Definition: powernode.hh:55
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(index_constant< i >={})
Returns the i-th child.
Definition: powernode.hh:104
ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:268
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
PowerNode()
Default constructor.
Definition: powernode.hh:317
const ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:288
void setChild(std::size_t i, T &t)
Sets the i-th child to the passed-in value.
Definition: powernode.hh:214
std::shared_ptr< T > childStorage(std::size_t i)
Returns the storage of the i-th child.
Definition: powernode.hh:197
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:90
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)