dune-typetree  2.3.1
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 
9 #include <dune/common/array.hh>
10 #include <dune/common/typetraits.hh>
11 
13 #include <dune/typetree/utility.hh>
14 #include <dune/common/static_assert.hh>
15 
16 namespace Dune {
17  namespace TypeTree {
18 
24 #if HAVE_VARIADIC_TEMPLATES && HAVE_RVALUE_REFERENCES
25 
26 #ifndef DOXYGEN
27 
28  namespace {
29 
30  // prototype and end of recursion
31  template<typename T, typename It, typename... Args>
32  void assign_reference_pack_to_shared_ptr_array_unpack(It it, Args&&... args) {}
33 
34  template<typename T, typename It, typename Arg, typename... Args>
35  void assign_reference_pack_to_shared_ptr_array_unpack(It it, Arg&& arg, Args&&... args)
36  {
37  static_assert(is_same<T,typename remove_const<typename remove_reference<Arg>::type>::type>::value,"type mismatch during array conversion");
38  *it = convert_arg(std::forward<Arg>(arg));
39  assign_reference_pack_to_shared_ptr_array_unpack<T>(++it,std::forward<Args>(args)...);
40  }
41 
42  template<typename T, std::size_t n, typename... Args>
43  void assign_reference_pack_to_shared_ptr_array(array<shared_ptr<T>,n>& res, Args&&... args)
44  {
45  static_assert(sizeof...(Args) == n, "invalid number of arguments");
46  return assign_reference_pack_to_shared_ptr_array_unpack<T>(res.begin(),std::forward<Args>(args)...);
47  }
48 
49 
50  // prototype and end of recursion
51  template<typename T, typename It, typename... Args>
52  void assign_shared_ptr_pack_to_shared_ptr_array_unpack(It it, Args&&... args) {}
53 
54  template<typename T, typename It, typename Arg, typename... Args>
55  void assign_shared_ptr_pack_to_shared_ptr_array_unpack(It it, Arg&& arg, Args&&... args)
56  {
57  static_assert(is_same<T,typename std::remove_reference<Arg>::type::element_type>::value,"type mismatch during array conversion");
58  *it = arg;
59  assign_shared_ptr_pack_to_shared_ptr_array_unpack<T>(++it,args...);
60  }
61 
62  template<typename T, std::size_t n, typename... Args>
63  void assign_shared_ptr_pack_to_shared_ptr_array(array<shared_ptr<T>,n>& res, Args&&... args)
64  {
65  static_assert(sizeof...(Args) == n, "invalid number of arguments");
66  return assign_shared_ptr_pack_to_shared_ptr_array_unpack<T>(res.begin(),args...);
67  }
68 
69  } // anonymous namespace
70 
71 #endif
72 
73 #endif
74 
75 #ifndef DOXYGEN
76 
78  template<typename PowerNode, typename T, std::size_t k>
79  struct AssertPowerNodeChildCount
80  : public enable_if<is_same<
81  typename PowerNode::ChildType,
82  T>::value &&
83  PowerNode::CHILDREN == k,
84  T>
85  {};
86 
87 #endif
88 
94  template<typename T, std::size_t k>
95  class PowerNode
96  {
97 
98  public:
99 
101  static const bool isLeaf = false;
102 
104  static const bool isPower = true;
105 
107  static const bool isComposite = false;
108 
110  static const std::size_t CHILDREN = k;
111 
114 
116  typedef T ChildType;
117 
119  typedef shared_ptr<T> ChildStorageType;
120 
122  typedef shared_ptr<const T> ChildConstStorageType;
123 
125  typedef array<ChildStorageType,k> NodeStorage;
126 
127 
129  template<std::size_t i>
130  struct Child
131  {
132 
133  dune_static_assert((i < CHILDREN), "child index out of range");
134 
136  typedef T Type;
137 
139  typedef T type;
140 
143 
146  };
147 
150 
152 
155  template<std::size_t i>
156  T& child ()
157  {
158  dune_static_assert((i < CHILDREN), "child index out of range");
159  return *_children[i];
160  }
161 
163 
166  template<std::size_t i>
167  const T& child () const
168  {
169  dune_static_assert((i < CHILDREN), "child index out of range");
170  return *_children[i];
171  }
172 
174 
177  template<std::size_t i>
179  {
180  dune_static_assert((i < CHILDREN), "child index out of range");
181  return _children[i];
182  }
183 
185 
191  template<std::size_t i>
193  {
194  dune_static_assert((i < CHILDREN), "child index out of range");
195  return _children[i];
196  }
197 
199  template<std::size_t i>
200  void setChild (T& t)
201  {
202  dune_static_assert((i < CHILDREN), "child index out of range");
203  _children[i] = stackobject_to_shared_ptr(t);
204  }
205 
207  template<std::size_t i>
209  {
210  dune_static_assert((i < CHILDREN), "child index out of range");
211  _children[i] = st;
212  }
213 
215 
216 
219 
221 
224  T& child (std::size_t i)
225  {
226  assert(i < CHILDREN && "child index out of range");
227  return *_children[i];
228  }
229 
231 
234  const T& child (std::size_t i) const
235  {
236  assert(i < CHILDREN && "child index out of range");
237  return *_children[i];
238  }
239 
241 
245  {
246  assert(i < CHILDREN && "child index out of range");
247  return _children[i];
248  }
249 
251 
257  ChildConstStorageType childStorage (std::size_t i) const
258  {
259  assert(i < CHILDREN && "child index out of range");
260  return (_children[i]);
261  }
262 
264  void setChild (std::size_t i, T& t)
265  {
266  assert(i < CHILDREN && "child index out of range");
267  _children[i] = stackobject_to_shared_ptr(t);
268  }
269 
271  void setChild (std::size_t i, ChildStorageType st)
272  {
273  assert(i < CHILDREN && "child index out of range");
274  _children[i] = st;
275  }
276 
277  const NodeStorage& nodeStorage() const
278  {
279  return _children;
280  }
281 
283 
286 
287  protected:
288 
290 
299  {}
300 
302  explicit PowerNode(const NodeStorage& children)
303  : _children(children)
304  {}
305 
307  explicit PowerNode (T& t, bool distinct_objects = true)
308  {
309  if (distinct_objects)
310  {
311  for (typename NodeStorage::iterator it = _children.begin(); it != _children.end(); ++it)
312  *it = make_shared<T>(t);
313  }
314  else
315  {
316  shared_ptr<T> sp = stackobject_to_shared_ptr(t);
317  std::fill(_children.begin(),_children.end(),sp);
318  }
319  }
320 
321 #ifdef DOXYGEN
322 
324 
334  PowerNode(T& t1, T& t2, ...)
335  {}
336 
337 #else
338 
339 #if HAVE_VARIADIC_TEMPLATES && HAVE_RVALUE_REFERENCES
340 
341 
342  // this weird signature avoids shadowing other 1-argument constructors
343  template<typename C0, typename C1, typename... Children>
344  PowerNode (C0&& c0, C1&& c1, Children&&... children)
345  {
346  assign_reference_pack_to_shared_ptr_array(_children,std::forward<C0>(c0),std::forward<C1>(c1),std::forward<Children>(children)...);
347  }
348 
349  // this weird signature avoids shadowing other 1-argument constructors
350  template<typename C0, typename C1, typename... Children>
351  PowerNode (shared_ptr<C0> c0, shared_ptr<C1> c1, shared_ptr<Children>... children)
352  {
353  assign_shared_ptr_pack_to_shared_ptr_array(_children,c0,c1,children...);
354  }
355 
356 #else
357 
358  template<typename U>
359  PowerNode (typename AssertPowerNodeChildCount<PowerNode,U,2>::type& c0,
360  U& c1)
361  {
362  _children[0] = stackobject_to_shared_ptr(c0);
363  _children[1] = stackobject_to_shared_ptr(c1);
364  }
365 
366  template<typename U>
367  PowerNode (typename AssertPowerNodeChildCount<PowerNode,U,3>::type& c0,
368  U& c1,
369  U& c2)
370  {
371  _children[0] = stackobject_to_shared_ptr(c0);
372  _children[1] = stackobject_to_shared_ptr(c1);
373  _children[2] = stackobject_to_shared_ptr(c2);
374  }
375 
376  template<typename U>
377  PowerNode (typename AssertPowerNodeChildCount<PowerNode,U,4>::type& c0,
378  U& c1,
379  U& c2,
380  U& c3)
381  {
382  _children[0] = stackobject_to_shared_ptr(c0);
383  _children[1] = stackobject_to_shared_ptr(c1);
384  _children[2] = stackobject_to_shared_ptr(c2);
385  _children[3] = stackobject_to_shared_ptr(c3);
386  }
387 
388  template<typename U>
389  PowerNode (typename AssertPowerNodeChildCount<PowerNode,U,5>::type& c0,
390  U& c1,
391  U& c2,
392  U& c3,
393  U& c4)
394  {
395  _children[0] = stackobject_to_shared_ptr(c0);
396  _children[1] = stackobject_to_shared_ptr(c1);
397  _children[2] = stackobject_to_shared_ptr(c2);
398  _children[3] = stackobject_to_shared_ptr(c3);
399  _children[4] = stackobject_to_shared_ptr(c4);
400  }
401 
402  template<typename U>
403  PowerNode (typename AssertPowerNodeChildCount<PowerNode,U,6>::type& c0,
404  U& c1,
405  U& c2,
406  U& c3,
407  U& c4,
408  U& c5)
409  {
410  _children[0] = stackobject_to_shared_ptr(c0);
411  _children[1] = stackobject_to_shared_ptr(c1);
412  _children[2] = stackobject_to_shared_ptr(c2);
413  _children[3] = stackobject_to_shared_ptr(c3);
414  _children[4] = stackobject_to_shared_ptr(c4);
415  _children[5] = stackobject_to_shared_ptr(c5);
416  }
417 
418  template<typename U>
419  PowerNode (typename AssertPowerNodeChildCount<PowerNode,U,7>::type& c0,
420  U& c1,
421  U& c2,
422  U& c3,
423  U& c4,
424  U& c5,
425  U& c6)
426  {
427  _children[0] = stackobject_to_shared_ptr(c0);
428  _children[1] = stackobject_to_shared_ptr(c1);
429  _children[2] = stackobject_to_shared_ptr(c2);
430  _children[3] = stackobject_to_shared_ptr(c3);
431  _children[4] = stackobject_to_shared_ptr(c4);
432  _children[5] = stackobject_to_shared_ptr(c5);
433  _children[6] = stackobject_to_shared_ptr(c6);
434  }
435 
436  template<typename U>
437  PowerNode (typename AssertPowerNodeChildCount<PowerNode,U,8>::type& c0,
438  U& c1,
439  U& c2,
440  U& c3,
441  U& c4,
442  U& c5,
443  U& c6,
444  U& c7)
445  {
446  _children[0] = stackobject_to_shared_ptr(c0);
447  _children[1] = stackobject_to_shared_ptr(c1);
448  _children[2] = stackobject_to_shared_ptr(c2);
449  _children[3] = stackobject_to_shared_ptr(c3);
450  _children[4] = stackobject_to_shared_ptr(c4);
451  _children[5] = stackobject_to_shared_ptr(c5);
452  _children[6] = stackobject_to_shared_ptr(c6);
453  _children[7] = stackobject_to_shared_ptr(c7);
454  }
455 
456  template<typename U>
457  PowerNode (typename AssertPowerNodeChildCount<PowerNode,U,9>::type& c0,
458  U& c1,
459  U& c2,
460  U& c3,
461  U& c4,
462  U& c5,
463  U& c6,
464  U& c7,
465  U& c8)
466  {
467  _children[0] = stackobject_to_shared_ptr(c0);
468  _children[1] = stackobject_to_shared_ptr(c1);
469  _children[2] = stackobject_to_shared_ptr(c2);
470  _children[3] = stackobject_to_shared_ptr(c3);
471  _children[4] = stackobject_to_shared_ptr(c4);
472  _children[5] = stackobject_to_shared_ptr(c5);
473  _children[6] = stackobject_to_shared_ptr(c6);
474  _children[7] = stackobject_to_shared_ptr(c7);
475  _children[8] = stackobject_to_shared_ptr(c8);
476  }
477 
478  template<typename U>
479  PowerNode (typename AssertPowerNodeChildCount<PowerNode,U,10>::type& c0,
480  U& c1,
481  U& c2,
482  U& c3,
483  U& c4,
484  U& c5,
485  U& c6,
486  U& c7,
487  U& c8,
488  U& c9)
489  {
490  _children[0] = stackobject_to_shared_ptr(c0);
491  _children[1] = stackobject_to_shared_ptr(c1);
492  _children[2] = stackobject_to_shared_ptr(c2);
493  _children[3] = stackobject_to_shared_ptr(c3);
494  _children[4] = stackobject_to_shared_ptr(c4);
495  _children[5] = stackobject_to_shared_ptr(c5);
496  _children[6] = stackobject_to_shared_ptr(c6);
497  _children[7] = stackobject_to_shared_ptr(c7);
498  _children[8] = stackobject_to_shared_ptr(c8);
499  _children[9] = stackobject_to_shared_ptr(c9);
500  }
501 
502 #endif // C++0x
503 
504 #endif // DOXYGEN
505 
507 
508  private:
509  NodeStorage _children;
510  };
511 
513 
514  } // namespace TypeTree
515 } //namespace Dune
516 
517 #endif // DUNE_TYPETREE_POWERNODE_HH
static const bool isLeaf
Mark this class as non leaf in the dune-typetree.
Definition: powernode.hh:101
PowerNode(const NodeStorage &children)
Initialize the PowerNode with a copy of the passed-in storage type.
Definition: powernode.hh:302
ChildStorageType Storage
The storage type of the child.
Definition: powernode.hh:142
ChildConstStorageType childStorage() const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:192
const T & child() const
Returns the i-th child (const version).
Definition: powernode.hh:167
ChildStorageType childStorage(std::size_t i)
Returns the storage of the i-th child.
Definition: powernode.hh:244
ChildConstStorageType childStorage(std::size_t i) const
Returns the storage of the i-th child (const version).
Definition: powernode.hh:257
Tag designating a power node.
Definition: nodetags.hh:19
ChildConstStorageType ConstStorage
The const storage type of the child.
Definition: powernode.hh:145
void setChild(std::size_t i, T &t)
Sets the i-th child to the passed-in value.
Definition: powernode.hh:264
PowerNode()
Default constructor.
Definition: powernode.hh:298
static const bool isPower
Mark this class as a power in the dune-typetree.
Definition: powernode.hh:104
static const std::size_t CHILDREN
The number of children.
Definition: powernode.hh:110
void setChild(ChildStorageType st)
Sets the stored value representing the i-th child to the passed-in value.
Definition: powernode.hh:208
T & child()
Returns the i-th child.
Definition: powernode.hh:156
const NodeStorage & nodeStorage() const
Definition: powernode.hh:277
PowerNode(T &t, bool distinct_objects=true)
Initialize all children with copies of a storage object constructed from the parameter t...
Definition: powernode.hh:307
dune_static_assert((i< CHILDREN),"child index out of range")
Collect k instances of type T within a dune-typetree.
Definition: powernode.hh:95
T type
The type of the child.
Definition: powernode.hh:139
T ChildType
The type of each child.
Definition: powernode.hh:116
PowerNode(T &t1, T &t2,...)
Initialize all children with the passed-in objects.
Definition: powernode.hh:334
static const bool isComposite
Mark this class as a non composite in the dune-typetree.
Definition: powernode.hh:107
PowerNodeTag NodeTag
The type tag that describes a PowerNode.
Definition: powernode.hh:113
ChildStorageType childStorage()
Returns the storage of the i-th child.
Definition: powernode.hh:178
array< ChildStorageType, k > NodeStorage
The type used for storing the children.
Definition: powernode.hh:125
static const std::size_t value
Definition: compositenode.hh:38
T & child(std::size_t i)
Returns the i-th child.
Definition: powernode.hh:224
shared_ptr< const T > ChildConstStorageType
The const version of the storage type of each child.
Definition: powernode.hh:122
Access to the type and storage type of the i-th child.
Definition: powernode.hh:130
const T & child(std::size_t i) const
Returns the i-th child (const version).
Definition: powernode.hh:234
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:271
void setChild(T &t)
Sets the i-th child to the passed-in value.
Definition: powernode.hh:200
shared_ptr< T > ChildStorageType
The storage type of each child.
Definition: powernode.hh:119
T Type
The type of the child.
Definition: powernode.hh:136