"Fossies" - the Fresh Open Source Software Archive 
Member "dune-typetree-2.8.0/dune/typetree/powernode.hh" (31 Aug 2021, 11649 Bytes) of package /linux/misc/dune/dune-typetree-2.8.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "powernode.hh" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.8.0_vs_2.9.0.
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
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
20 namespace Dune {
21 namespace TypeTree {
22
23 /** \addtogroup Nodes
24 * \ingroup TypeTree
25 * \{
26 */
27
28
29 #ifndef DOXYGEN
30
31 //! Helper struct to make constructor enabling mechanism in PowerNode more readable.
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
43 /** \brief Collect k instances of type T within a \ref TypeTree.
44 *
45 * \tparam T The base type
46 * \tparam k The number of instances this node should collect
47 */
48 template<typename T, std::size_t k>
49 class PowerNode
50 {
51
52 public:
53
54 //! Mark this class as non leaf in the \ref TypeTree.
55 static const bool isLeaf = false;
56
57 //! Mark this class as a power in the \ref TypeTree.
58 static const bool isPower = true;
59
60 //! Mark this class as a non composite in the \ref TypeTree.
61 static const bool isComposite = false;
62
63 //! The number of children.
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
71 //! The type tag that describes a PowerNode.
72 typedef PowerNodeTag NodeTag;
73
74 //! The type of each child.
75 typedef T ChildType;
76
77 //! The type used for storing the children.
78 typedef std::array<std::shared_ptr<T>,k> NodeStorage;
79
80
81 //! Access to the type and storage type of the i-th child.
82 template<std::size_t i>
83 struct Child
84 {
85
86 static_assert((i < CHILDREN), "child index out of range");
87
88 //! The type of the child.
89 typedef T Type;
90
91 //! The type of the child.
92 typedef T type;
93 };
94
95 //! @name Child Access (templated methods)
96 //! @{
97
98 //! Returns the i-th child.
99 /**
100 * \returns a reference to the i-th child.
101 */
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
109 //! Returns the i-th child (const version).
110 /**
111 * \returns a const reference to the i-th child.
112 */
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
120 //! Returns the storage of the i-th child.
121 /**
122 * \returns a copy of the object storing the i-th child.
123 */
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
131 //! Returns the storage of the i-th child (const version).
132 /**
133 * \returns a copy of the object storing the i-th child.
134 */
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
142 //! Sets the i-th child to the passed-in value.
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
150 //! Store the passed value in i-th child.
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
158 //! Sets the stored value representing the i-th child to the passed-in value.
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
166 //! @}
167
168
169 //! @name Child Access (Dynamic methods)
170 //! @{
171
172 //! Returns the i-th child.
173 /**
174 * \returns a reference to the i-th child.
175 */
176 T& child (std::size_t i)
177 {
178 assert(i < CHILDREN && "child index out of range");
179 return *_children[i];
180 }
181
182 //! Returns the i-th child (const version).
183 /**
184 * \returns a const reference to the i-th child.
185 */
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
192 //! Returns the storage of the i-th child.
193 /**
194 * \returns a copy of the object storing the i-th child.
195 */
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
202 //! Returns the storage of the i-th child (const version).
203 /**
204 * \returns a copy of the object storing the i-th child.
205 */
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
212 //! Sets the i-th child to the passed-in value.
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
219 //! Store the passed value in i-th child.
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
226 //! Sets the stored value representing the i-th child to the passed-in value.
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
238 //! @}
239
240 //! @name Nested Child Access
241 //! @{
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
260 //! Returns the child given by the list of indices.
261 /**
262 * This method simply forwards to the freestanding function child(). See that
263 * function for further information.
264 */
265 #ifdef DOXYGEN
266 template<typename... Indices>
267 ImplementationDefined& child (Indices... 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
280 //! Returns the child given by the list of indices.
281 /**
282 * This method simply forwards to the freestanding function child(). See that
283 * function for further information.
284 */
285 #ifdef DOXYGEN
286 template<typename... Indices>
287 const ImplementationDefined& child (Indices... 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
300 //! @}
301
302 //! @name Constructors
303 //! @{
304
305 protected:
306
307 //! Default constructor.
308 /**
309 * The default constructor is protected, as PowerNode is a utility
310 * class that needs to be filled with meaning by subclassing it
311 * and adding useful functionality to the subclass.
312 *
313 * \warning When using the default constructor, make sure to set ALL children
314 * by means of the setChild() methods!
315 */
316 PowerNode ()
317 {}
318
319 //! Initialize the PowerNode with a copy of the passed-in storage type.
320 explicit PowerNode (const NodeStorage& children)
321 : _children(children)
322 {}
323
324 //! Initialize all children with copies of a storage object constructed from the parameter \c t.
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
341 //! Initialize all children with the passed-in objects.
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
369 //! @}
370
371 private:
372 NodeStorage _children;
373 };
374
375 //! \} group Nodes
376
377 } // namespace TypeTree
378 } //namespace Dune
379
380 #endif // DUNE_TYPETREE_POWERNODE_HH