dune-typetree 3.0-dev
powernode.hh
Go to the documentation of this file.
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
10#include <dune/common/typetraits.hh>
11
15
16namespace Dune {
17 namespace TypeTree {
18
24#ifndef DOXYGEN
25
26 namespace {
27
28 // prototype and end of recursion
29 template<typename T, typename It, typename... Args>
30 void assign_reference_pack_to_shared_ptr_array_unpack(It it, Args&&... args) {}
31
32 template<typename T, typename It, typename Arg, typename... Args>
33 void assign_reference_pack_to_shared_ptr_array_unpack(It it, Arg&& arg, Args&&... args)
34 {
35 static_assert(std::is_same<T,typename std::remove_const<typename std::remove_reference<Arg>::type>::type>::value,"type mismatch during array conversion");
36 *it = convert_arg(std::forward<Arg>(arg));
37 assign_reference_pack_to_shared_ptr_array_unpack<T>(++it,std::forward<Args>(args)...);
38 }
39
40 template<typename T, std::size_t n, typename... Args>
41 void assign_reference_pack_to_shared_ptr_array(std::array<shared_ptr<T>,n>& res, Args&&... args)
42 {
43 static_assert(sizeof...(Args) == n, "invalid number of arguments");
44 return assign_reference_pack_to_shared_ptr_array_unpack<T>(res.begin(),std::forward<Args>(args)...);
45 }
46
47
48 // prototype and end of recursion
49 template<typename T, typename It, typename... Args>
50 void assign_shared_ptr_pack_to_shared_ptr_array_unpack(It it, Args&&... args) {}
51
52 template<typename T, typename It, typename Arg, typename... Args>
53 void assign_shared_ptr_pack_to_shared_ptr_array_unpack(It it, Arg&& arg, Args&&... args)
54 {
55 static_assert(std::is_same<T,typename std::remove_reference<Arg>::type::element_type>::value,"type mismatch during array conversion");
56 *it = arg;
57 assign_shared_ptr_pack_to_shared_ptr_array_unpack<T>(++it,args...);
58 }
59
60 template<typename T, std::size_t n, typename... Args>
61 void assign_shared_ptr_pack_to_shared_ptr_array(std::array<shared_ptr<T>,n>& res, Args&&... args)
62 {
63 static_assert(sizeof...(Args) == n, "invalid number of arguments");
64 return assign_shared_ptr_pack_to_shared_ptr_array_unpack<T>(res.begin(),args...);
65 }
66
67 } // anonymous namespace
68
69#endif
70
71#ifndef DOXYGEN
72
74 template<typename PowerNode, typename T, std::size_t k>
75 struct AssertPowerNodeChildCount
76 : public std::enable_if<std::is_same<
77 typename PowerNode::ChildType,
78 T>::value &&
79 PowerNode::CHILDREN == k,
80 T>
81 {};
82
83#endif
84
90 template<typename T, std::size_t k>
92 {
93
94 public:
95
97 static const bool isLeaf = false;
98
100 static const bool isPower = true;
101
103 static const bool isComposite = false;
104
106 static const std::size_t CHILDREN = k;
107
108 static constexpr std::size_t degree()
109 {
110 return k;
111 }
112
115
117 typedef T ChildType;
118
120 typedef shared_ptr<T> ChildStorageType;
121
123 typedef shared_ptr<const T> ChildConstStorageType;
124
126 typedef std::array<ChildStorageType,k> NodeStorage;
127
128
130 template<std::size_t i>
131 struct Child
132 {
133
134 static_assert((i < CHILDREN), "child index out of range");
135
137 typedef T Type;
138
140 typedef T type;
141
144
147 };
148
151
153
156 template<std::size_t i>
157 T& child (index_constant<i> = {})
158 {
159 static_assert((i < CHILDREN), "child index out of range");
160 return *_children[i];
161 }
162
164
167 template<std::size_t i>
168 const T& child (index_constant<i> = {}) const
169 {
170 static_assert((i < CHILDREN), "child index out of range");
171 return *_children[i];
172 }
173
175
178 template<std::size_t i>
179 ChildStorageType childStorage(index_constant<i> = {})
180 {
181 static_assert((i < CHILDREN), "child index out of range");
182 return _children[i];
183 }
184
186
192 template<std::size_t i>
193 ChildConstStorageType childStorage(index_constant<i> = {}) const
194 {
195 static_assert((i < CHILDREN), "child index out of range");
196 return _children[i];
197 }
198
200 template<std::size_t i>
201 void setChild (T& t, index_constant<i> = {})
202 {
203 static_assert((i < CHILDREN), "child index out of range");
204 _children[i] = stackobject_to_shared_ptr(t);
205 }
206
208 template<std::size_t i>
209 void setChild(T&& t, index_constant<i> = {})
210 {
211 static_assert((i < CHILDREN), "child index out of range");
212 _children[i] = convert_arg(std::move(t));
213 }
214
216 template<std::size_t i>
217 void setChild (ChildStorageType st, index_constant<i> = {})
218 {
219 static_assert((i < CHILDREN), "child index out of range");
220 _children[i] = st;
221 }
222
224
225
228
230
233 T& child (std::size_t i)
234 {
235 assert(i < CHILDREN && "child index out of range");
236 return *_children[i];
237 }
238
240
243 const T& child (std::size_t i) const
244 {
245 assert(i < CHILDREN && "child index out of range");
246 return *_children[i];
247 }
248
250
254 {
255 assert(i < CHILDREN && "child index out of range");
256 return _children[i];
257 }
258
260
267 {
268 assert(i < CHILDREN && "child index out of range");
269 return (_children[i]);
270 }
271
273 void setChild (std::size_t i, T& t)
274 {
275 assert(i < CHILDREN && "child index out of range");
276 _children[i] = stackobject_to_shared_ptr(t);
277 }
278
280 void setChild(std::size_t i, T&& t)
281 {
282 assert(i < CHILDREN && "child index out of range");
283 _children[i] = convert_arg(std::move(t));
284 }
285
287 void setChild (std::size_t i, ChildStorageType st)
288 {
289 assert(i < CHILDREN && "child index out of range");
290 _children[i] = st;
291 }
292
294 {
295 return _children;
296 }
297
299
302
303 // The following two methods require a little bit of SFINAE trickery to work correctly:
304 // We have to make sure that they don't shadow the methods for direct child access because
305 // those get called by the generic child() machinery. If that machinery picks up the methods
306 // defined below, we have an infinite recursion.
307 // So the methods make sure that either
308 //
309 // * there are more than one argument. In that case, we got multiple indices and can forward
310 // to the general machine.
311 //
312 // * the first argument is not a valid flat index, i.e. either a std::size_t or an index_constant.
313 // The argument thus has to be some kind of TreePath instance that we can also pass to the
314 // generic machine.
315 //
316 // The above SFINAE logic works, but there is still a problem with the return type deduction.
317 // We have to do a lazy lookup of the return type after SFINAE has succeeded, otherwise the return
318 // type deduction will trigger the infinite recursion.
319
321
325#ifdef DOXYGEN
326 template<typename... Indices>
327 ImplementationDefined& child(Indices... indices)
328#else
329 template<typename I0, typename... I>
330 auto child(I0 i0, I... i)
331 -> typename std::enable_if<
332 (sizeof...(I) > 0) || !is_flat_index<I0>{},
333 impl::_lazy_member_child_decltype<PowerNode>
334 >::type::template evaluate<I0,I...>::type
335#endif
336 {
337 static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
338 "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
339 );
340 return Dune::TypeTree::child(*this,i0,i...);
341 }
342
344
348#ifdef DOXYGEN
349 template<typename... Indices>
350 const ImplementationDefined& child(Indices... indices)
351#else
352 template<typename I0, typename... I>
353 auto child(I0 i0, I... i) const
354 -> typename std::enable_if<
355 (sizeof...(I) > 0) || !is_flat_index<I0>{},
356 impl::_lazy_member_child_decltype<const PowerNode>
357 >::type::template evaluate<I0,I...>::type
358#endif
359 {
360 static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}),
361 "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead."
362 );
363 return Dune::TypeTree::child(*this,i0,i...);
364 }
365
367
370
371 protected:
372
374
383 {}
384
386 explicit PowerNode(const NodeStorage& children)
387 : _children(children)
388 {}
389
391 explicit PowerNode (T& t, bool distinct_objects = true)
392 {
393 if (distinct_objects)
394 {
395 for (typename NodeStorage::iterator it = _children.begin(); it != _children.end(); ++it)
396 *it = std::make_shared<T>(t);
397 }
398 else
399 {
400 shared_ptr<T> sp = stackobject_to_shared_ptr(t);
401 std::fill(_children.begin(),_children.end(),sp);
402 }
403 }
404
405#ifdef DOXYGEN
406
408
418 PowerNode(T& t1, T& t2, ...)
419 {}
420
421#else
422
423 // this weird signature avoids shadowing other 1-argument constructors
424 template<typename C0, typename C1, typename... Children>
425 PowerNode (C0&& c0, C1&& c1, Children&&... children)
426 {
427 assign_reference_pack_to_shared_ptr_array(_children,std::forward<C0>(c0),std::forward<C1>(c1),std::forward<Children>(children)...);
428 }
429
430 // this weird signature avoids shadowing other 1-argument constructors
431 template<typename C0, typename C1, typename... Children>
432 PowerNode (shared_ptr<C0> c0, shared_ptr<C1> c1, shared_ptr<Children>... children)
433 {
434 assign_shared_ptr_pack_to_shared_ptr_array(_children,c0,c1,children...);
435 }
436
437#endif // DOXYGEN
438
440
441 private:
442 NodeStorage _children;
443 };
444
446
447 } // namespace TypeTree
448} //namespace Dune
449
450#endif // DUNE_TYPETREE_POWERNODE_HH
typename impl::_is_flat_index< std::decay_t< T > >::type is_flat_index
Type trait that determines whether T is a flat index in the context of child extraction.
Definition childextraction.hh:366
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
Definition accumulate_static.hh:13
Tag designating a power node.
Definition nodetags.hh:19
Collect k instances of type T within a dune-typetree.
Definition powernode.hh:92
void setChild(T &t, index_constant< i >={})
Sets the i-th child to the passed-in value.
Definition powernode.hh:201
ChildStorageType childStorage(std::size_t i)
Returns the storage of the i-th child.
Definition powernode.hh:253
T & child(std::size_t i)
Returns the i-th child.
Definition powernode.hh:233
const T & child(index_constant< i >={}) const
Returns the i-th child (const version).
Definition powernode.hh:168
PowerNode(T &t1, T &t2,...)
Initialize all children with the passed-in objects.
Definition powernode.hh:418
ChildConstStorageType childStorage(std::size_t i) const
Returns the storage of the i-th child (const version).
Definition powernode.hh:266
const NodeStorage & nodeStorage() const
Definition powernode.hh:293
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:287
PowerNode(T &t, bool distinct_objects=true)
Initialize all children with copies of a storage object constructed from the parameter t.
Definition powernode.hh:391
PowerNodeTag NodeTag
The type tag that describes a PowerNode.
Definition powernode.hh:114
const T & child(std::size_t i) const
Returns the i-th child (const version).
Definition powernode.hh:243
std::array< ChildStorageType, k > NodeStorage
The type used for storing the children.
Definition powernode.hh:126
static const std::size_t CHILDREN
The number of children.
Definition powernode.hh:106
shared_ptr< const T > ChildConstStorageType
The const version of the storage type of each child.
Definition powernode.hh:123
static const bool isComposite
Mark this class as a non composite in the dune-typetree.
Definition powernode.hh:103
static constexpr std::size_t degree()
Definition powernode.hh:108
static const bool isLeaf
Mark this class as non leaf in the dune-typetree.
Definition powernode.hh:97
shared_ptr< T > ChildStorageType
The storage type of each child.
Definition powernode.hh:120
static const bool isPower
Mark this class as a power in the dune-typetree.
Definition powernode.hh:100
void setChild(ChildStorageType st, index_constant< i >={})
Sets the stored value representing the i-th child to the passed-in value.
Definition powernode.hh:217
PowerNode(const NodeStorage &children)
Initialize the PowerNode with a copy of the passed-in storage type.
Definition powernode.hh:386
T ChildType
The type of each child.
Definition powernode.hh:117
T & child(index_constant< i >={})
Returns the i-th child.
Definition powernode.hh:157
ChildConstStorageType childStorage(index_constant< i >={}) const
Returns the storage of the i-th child (const version).
Definition powernode.hh:193
ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition powernode.hh:327
void setChild(std::size_t i, T &&t)
Store the passed value in i-th child.
Definition powernode.hh:280
void setChild(T &&t, index_constant< i >={})
Store the passed value in i-th child.
Definition powernode.hh:209
ChildStorageType childStorage(index_constant< i >={})
Returns the storage of the i-th child.
Definition powernode.hh:179
PowerNode()
Default constructor.
Definition powernode.hh:382
const ImplementationDefined & child(Indices... indices)
Returns the child given by the list of indices.
Definition powernode.hh:350
void setChild(std::size_t i, T &t)
Sets the i-th child to the passed-in value.
Definition powernode.hh:273
Access to the type and storage type of the i-th child.
Definition powernode.hh:132
T type
The type of the child.
Definition powernode.hh:140
T Type
The type of the child.
Definition powernode.hh:137
ChildStorageType Storage
The storage type of the child.
Definition powernode.hh:143
ChildConstStorageType ConstStorage
The const storage type of the child.
Definition powernode.hh:146