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
22namespace 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>
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>
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
T & child(std::size_t i)
Returns the i-th child.
Definition: powernode.hh:175
const T & child(index_constant< i >={}) const
Returns the i-th child (const version).
Definition: powernode.hh:113
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
std::shared_ptr< T > childStorage(index_constant< i >={})
Returns the storage of the i-th child.
Definition: powernode.hh:124
PowerNode(T &t1, T &t2,...)
Initialize all children with the passed-in objects.
Definition: powernode.hh:341
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
const T & child(std::size_t i) const
Returns the i-th child (const version).
Definition: powernode.hh:185
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
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
static const bool isLeaf
Mark this class as non leaf in the dune-typetree.
Definition: powernode.hh:57
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(index_constant< i >={})
Returns the i-th child.
Definition: powernode.hh:102
ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:266
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
PowerNode()
Default constructor.
Definition: powernode.hh:315
const ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition: powernode.hh:286
void setChild(std::size_t i, T &t)
Sets the i-th child to the passed-in value.
Definition: powernode.hh:212
std::shared_ptr< T > childStorage(std::size_t i)
Returns the storage of the i-th child.
Definition: powernode.hh:195
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:88
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 24, 23:30, 2024)