DUNE PDELab (2.8)

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::CHILDREN == 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 static const std::size_t CHILDREN = k;
65
66 static constexpr auto degree ()
67 {
68 return std::integral_constant<std::size_t,k>{};
69 }
70
73
75 typedef T ChildType;
76
78 typedef std::array<std::shared_ptr<T>,k> NodeStorage;
79
80
82 template<std::size_t i>
83 struct Child
84 {
85
86 static_assert((i < CHILDREN), "child index out of range");
87
89 typedef T Type;
90
92 typedef T type;
93 };
94
97
99
102 template<std::size_t i>
103 T& child (index_constant<i> = {})
104 {
105 static_assert((i < CHILDREN), "child index out of range");
106 return *_children[i];
107 }
108
110
113 template<std::size_t i>
114 const T& child (index_constant<i> = {}) const
115 {
116 static_assert((i < CHILDREN), "child index out of range");
117 return *_children[i];
118 }
119
121
124 template<std::size_t i>
125 std::shared_ptr<T> childStorage (index_constant<i> = {})
126 {
127 static_assert((i < CHILDREN), "child index out of range");
128 return _children[i];
129 }
130
132
135 template<std::size_t i>
136 std::shared_ptr<const T> childStorage (index_constant<i> = {}) const
137 {
138 static_assert((i < CHILDREN), "child index out of range");
139 return _children[i];
140 }
141
143 template<std::size_t i>
144 void setChild (T& t, index_constant<i> = {})
145 {
146 static_assert((i < CHILDREN), "child index out of range");
147 _children[i] = stackobject_to_shared_ptr(t);
148 }
149
151 template<std::size_t i>
152 void setChild (T&& t, index_constant<i> = {})
153 {
154 static_assert((i < CHILDREN), "child index out of range");
155 _children[i] = convert_arg(std::move(t));
156 }
157
159 template<std::size_t i>
160 void setChild (std::shared_ptr<T> st, index_constant<i> = {})
161 {
162 static_assert((i < CHILDREN), "child index out of range");
163 _children[i] = std::move(st);
164 }
165
167
168
171
173
176 T& child (std::size_t i)
177 {
178 assert(i < CHILDREN && "child index out of range");
179 return *_children[i];
180 }
181
183
186 const T& child (std::size_t i) const
187 {
188 assert(i < CHILDREN && "child index out of range");
189 return *_children[i];
190 }
191
193
196 std::shared_ptr<T> childStorage (std::size_t i)
197 {
198 assert(i < CHILDREN && "child index out of range");
199 return _children[i];
200 }
201
203
206 std::shared_ptr<const T> childStorage (std::size_t i) const
207 {
208 assert(i < CHILDREN && "child index out of range");
209 return _children[i];
210 }
211
213 void setChild (std::size_t i, T& t)
214 {
215 assert(i < CHILDREN && "child index out of range");
216 _children[i] = stackobject_to_shared_ptr(t);
217 }
218
220 void setChild (std::size_t i, T&& t)
221 {
222 assert(i < CHILDREN && "child index out of range");
223 _children[i] = convert_arg(std::move(t));
224 }
225
227 void setChild (std::size_t i, std::shared_ptr<T> st)
228 {
229 assert(i < CHILDREN && "child index out of range");
230 _children[i] = std::move(st);
231 }
232
233 const NodeStorage& nodeStorage () const
234 {
235 return _children;
236 }
237
239
242
243 // The following two methods require a little bit of SFINAE trickery to work correctly:
244 // We have to make sure that they don't shadow the methods for direct child access because
245 // those get called by the generic child() machinery. If that machinery picks up the methods
246 // defined below, we have an infinite recursion.
247 // So the methods make sure that either
248 //
249 // * there are more than one argument. In that case, we got multiple indices and can forward
250 // to the general machine.
251 //
252 // * the first argument is not a valid flat index, i.e. either a std::size_t or an index_constant.
253 // The argument thus has to be some kind of TreePath instance that we can also pass to the
254 // generic machine.
255 //
256 // The above SFINAE logic works, but there is still a problem with the return type deduction.
257 // We have to do a lazy lookup of the return type after SFINAE has succeeded, otherwise the return
258 // type deduction will trigger the infinite recursion.
259
261
265#ifdef DOXYGEN
266 template<typename... Indices>
268#else
269 template<typename I0, typename... I,
270 std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
271 decltype(auto) child (I0 i0, I... i)
272#endif
273 {
274 static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
275 "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
276 );
277 return Dune::TypeTree::child(*this,i0,i...);
278 }
279
281
285#ifdef DOXYGEN
286 template<typename... Indices>
288#else
289 template<typename I0, typename... I,
290 std::enable_if_t<(sizeof...(I) > 0) || IsTreePath<I0>::value, int > = 0>
291 decltype(auto) child (I0 i0, I... i) const
292#endif
293 {
294 static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
295 "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
296 );
297 return Dune::TypeTree::child(*this,i0,i...);
298 }
299
301
304
305 protected:
306
308
317 {}
318
320 explicit PowerNode (const NodeStorage& children)
321 : _children(children)
322 {}
323
325 explicit PowerNode (T& t, bool distinct_objects = true)
326 {
327 if (distinct_objects)
328 {
329 for (typename NodeStorage::iterator it = _children.begin(); it != _children.end(); ++it)
330 *it = std::make_shared<T>(t);
331 }
332 else
333 {
334 std::shared_ptr<T> sp = stackobject_to_shared_ptr(t);
335 std::fill(_children.begin(),_children.end(),sp);
336 }
337 }
338
339#ifdef DOXYGEN
340
342 PowerNode(T& t1, T& t2, ...)
343 {}
344
345#else
346
347 template<typename... Children,
348 std::enable_if_t<
349 std::conjunction<std::is_same<ChildType, std::decay_t<Children>>...>::value
350 ,int> = 0>
351 PowerNode (Children&&... children)
352 {
353 static_assert(CHILDREN == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
354 _children = NodeStorage{convert_arg(std::forward<Children>(children))...};
355 }
356
357 template<typename... Children,
358 std::enable_if_t<
359 std::conjunction<std::is_same<ChildType, Children>...>::value
360 ,int> = 0>
361 PowerNode (std::shared_ptr<Children>... children)
362 {
363 static_assert(CHILDREN == sizeof...(Children), "PowerNode constructor is called with incorrect number of children");
364 _children = NodeStorage{children...};
365 }
366
367#endif // DOXYGEN
368
370
371 private:
372 NodeStorage _children;
373 };
374
376
377 } // namespace TypeTree
378} //namespace Dune
379
380#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:144
T & child(std::size_t i)
Returns the i-th child.
Definition: powernode.hh:176
const T & child(index_constant< i >={}) const
Returns the i-th child (const version).
Definition: powernode.hh:114
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:160
std::shared_ptr< T > childStorage(index_constant< i >={})
Returns the storage of the i-th child.
Definition: powernode.hh:125
PowerNode(T &t1, T &t2,...)
Initialize all children with the passed-in objects.
Definition: powernode.hh:342
std::array< std::shared_ptr< T >, k > NodeStorage
The type used for storing the children.
Definition: powernode.hh:78
std::shared_ptr< const T > childStorage(index_constant< i >={}) const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:136
PowerNode(T &t, bool distinct_objects=true)
Initialize all children with copies of a storage object constructed from the parameter t.
Definition: powernode.hh:325
PowerNodeTag NodeTag
The type tag that describes a PowerNode.
Definition: powernode.hh:72
const T & child(std::size_t i) const
Returns the i-th child (const version).
Definition: powernode.hh:186
std::shared_ptr< const T > childStorage(std::size_t i) const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:206
static const std::size_t CHILDREN
The number of children.
Definition: powernode.hh:64
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:227
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:320
T ChildType
The type of each child.
Definition: powernode.hh:75
T & child(index_constant< i >={})
Returns the i-th child.
Definition: powernode.hh:103
ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:267
void setChild(std::size_t i, T &&t)
Store the passed value in i-th child.
Definition: powernode.hh:220
void setChild(T &&t, index_constant< i >={})
Store the passed value in i-th child.
Definition: powernode.hh:152
PowerNode()
Default constructor.
Definition: powernode.hh:316
const ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:287
void setChild(std::size_t i, T &t)
Sets the i-th child to the passed-in value.
Definition: powernode.hh:213
std::shared_ptr< T > childStorage(std::size_t i)
Returns the storage of the i-th child.
Definition: powernode.hh:196
Traits for type conversions and type information.
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:49
Dune namespace.
Definition: alignedallocator.hh:11
std::shared_ptr< T > stackobject_to_shared_ptr(T &t)
Create a shared_ptr for a stack-allocated object.
Definition: shared_ptr.hh:70
Dummy struct used for documentation purposes.
Definition: documentation.hh:40
Check if type represents a tree path.
Definition: typetraits.hh:190
Tag designating a power node.
Definition: nodetags.hh:19
Access to the type and storage type of the i-th child.
Definition: powernode.hh:84
T type
The type of the child.
Definition: powernode.hh:92
T Type
The type of the child.
Definition: powernode.hh:89
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 24, 22:29, 2024)