DUNE PDELab (2.7)

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 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
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>
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>
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<
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<
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
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
T & child(std::size_t i)
Returns the i-th child.
Definition: powernode.hh:191
const T & child(index_constant< i >={}) const
Returns the i-th child (const version).
Definition: powernode.hh:126
PowerNode(T &t1, T &t2,...)
Initialize all children with the passed-in objects.
Definition: powernode.hh:360
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
const T & child(std::size_t i) const
Returns the i-th child (const version).
Definition: powernode.hh:201
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
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 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
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
T & child(index_constant< i >={})
Returns the i-th child.
Definition: powernode.hh:115
ChildConstStorageType childStorage(index_constant< i >={}) const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:151
ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:285
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
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
const ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:305
void setChild(std::size_t i, T &t)
Sets the i-th child to the passed-in value.
Definition: powernode.hh:231
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:179
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:49
Dune namespace.
Definition: alignedallocator.hh:14
shared_ptr< T > stackobject_to_shared_ptr(T &t)
Create a shared_ptr for a stack-allocated object.
Definition: shared_ptr.hh:75
Dummy struct used for documentation purposes.
Definition: documentation.hh:40
forms the logical conjunction of the type traits B...
Definition: type_traits.hh:445
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:90
T type
The type of the child.
Definition: powernode.hh:98
T Type
The type of the child.
Definition: powernode.hh:95
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)