dune-typetree  2.3.1
transformation.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_TRANSFORMATION_HH
5 #define DUNE_TYPETREE_TRANSFORMATION_HH
6 
7 #include <dune/common/exceptions.hh>
8 #include <dune/common/typetraits.hh>
9 #include <dune/common/shared_ptr.hh>
10 #include <dune/common/array.hh>
11 #include <dune/common/tuples.hh>
14 #include <dune/typetree/utility.hh>
15 
16 
17 namespace Dune {
18  namespace TypeTree {
19 
25 #ifdef DOXYGEN
26 
28 
47  template<typename SourceNode, typename Transformation, typename Tag>
48  void registerNodeTransformation(SourceNode*, Transformation*, Tag*);
49 
50 #else // DOXYGEN
51 
62  template<typename S, typename T, typename Tag>
63  struct LookupNodeTransformation
64  {
65 
66  typedef DUNE_DECLTYPE(registerNodeTransformation(declptr<S>(),declptr<T>(),declptr<Tag>())) lookup_type;
67 
68  typedef typename evaluate_if_meta_function<
69  lookup_type
70  >::type type;
71 
72  dune_static_assert((!is_same<type,void>::value), "Unable to find valid transformation descriptor");
73  };
74 
75  struct EmptyNodeTransformation;
76 
77  // Specialization for EmptyNode. This is mainly here to save the user from possible
78  // ambiguities when looking up registerNodeTransformation().
79  template<typename S, typename T>
80  struct LookupNodeTransformation<S,T,EmptyNodeTag>
81  {
82  typedef EmptyNodeTransformation type;
83  };
84 
85 #endif // DOXYGEN
86 
87 
89 
98  template<typename SourceTree, typename Transformation, typename Tag = StartTag, bool recursive = true>
100  {
101 
102 #ifndef DOXYGEN
103 
104  typedef typename LookupNodeTransformation<SourceTree,Transformation,typename SourceTree::ImplementationTag>::type NodeTransformation;
105 
106  // the type of the new tree that will result from this transformation
108 
109  // the storage type of the new tree that will result from this transformation
111 
112 #endif // DOXYGEN
113 
115  typedef transformed_type Type;
116 
117 
119  static transformed_type transform(const SourceTree& s, const Transformation& t = Transformation())
120  {
122  }
123 
125  static transformed_type transform(const SourceTree& s, Transformation& t)
126  {
128  }
129 
131  static transformed_type transform(shared_ptr<const SourceTree> sp, const Transformation& t = Transformation())
132  {
134  }
135 
137  static transformed_type transform(shared_ptr<const SourceTree> sp, Transformation& t)
138  {
140  }
141 
144  static transformed_storage_type transform_storage(shared_ptr<const SourceTree> sp, const Transformation& t = Transformation())
145  {
147  }
148 
151  static transformed_storage_type transform_storage(shared_ptr<const SourceTree> sp, Transformation& t)
152  {
154  }
155 
156 
157  };
158 
159 #ifndef DOXYGEN // internal per-node implementations of the transformation algorithm
160 
161  // handle a leaf node - this is easy
162  template<typename S, typename T, bool recursive>
163  struct TransformTree<S,T,LeafNodeTag,recursive>
164  {
165  // get transformed type from specification
166  typedef typename LookupNodeTransformation<S,T,typename S::ImplementationTag>::type NodeTransformation;
167 
168  typedef typename NodeTransformation::transformed_type transformed_type;
169  typedef typename NodeTransformation::transformed_storage_type transformed_storage_type;
170 
171  // delegate instance transformation to per-node specification
172  static transformed_type transform(const S& s, T& t)
173  {
174  return NodeTransformation::transform(s,t);
175  }
176 
177  // delegate instance transformation to per-node specification
178  static transformed_type transform(const S& s, const T& t)
179  {
180  return NodeTransformation::transform(s,t);
181  }
182 
183  // delegate instance transformation to per-node specification
184  static transformed_type transform(shared_ptr<const S> sp, T& t)
185  {
186  return NodeTransformation::transform(sp,t);
187  }
188 
189  // delegate instance transformation to per-node specification
190  static transformed_type transform(shared_ptr<const S> sp, const T& t)
191  {
192  return NodeTransformation::transform(sp,t);
193  }
194 
195  static transformed_storage_type transform_storage(shared_ptr<const S> sp, T& t)
196  {
197  return NodeTransformation::transform_storage(sp,t);
198  }
199 
200  static transformed_storage_type transform_storage(shared_ptr<const S> sp, const T& t)
201  {
202  return NodeTransformation::transform_storage(sp,t);
203  }
204 
205  };
206 
207 
208  // common implementation for non-recursive transformation of non-leaf nodes
209  template<typename S, typename T>
210  struct TransformTreeNonRecursive
211  {
212  // get transformed type from specification
213  typedef typename LookupNodeTransformation<S,T,typename S::ImplementationTag>::type NodeTransformation;
214 
215  typedef typename NodeTransformation::transformed_type transformed_type;
216  typedef typename NodeTransformation::transformed_storage_type transformed_storage_type;
217 
218  // delegate instance transformation to per-node specification
219  static transformed_type transform(const S& s, T& t)
220  {
221  return NodeTransformation::transform(s,t);
222  }
223 
224  // delegate instance transformation to per-node specification
225  static transformed_type transform(const S& s, const T& t)
226  {
227  return NodeTransformation::transform(s,t);
228  }
229 
230  // delegate instance transformation to per-node specification
231  static transformed_type transform(shared_ptr<const S> sp, T& t)
232  {
233  return NodeTransformation::transform(sp,t);
234  }
235 
236  // delegate instance transformation to per-node specification
237  static transformed_type transform(shared_ptr<const S> sp, const T& t)
238  {
239  return NodeTransformation::transform(sp,t);
240  }
241 
242  static transformed_storage_type transform_storage(shared_ptr<const S> sp, T& t)
243  {
244  return NodeTransformation::transform_storage(sp,t);
245  }
246 
247  static transformed_storage_type transform_storage(shared_ptr<const S> sp, const T& t)
248  {
249  return NodeTransformation::transform_storage(sp,t);
250  }
251 
252  };
253 
254 
255  // handle power tag - a little more tricky
256  template<typename S, typename T>
257  struct TransformTree<S,T,PowerNodeTag,true>
258  {
259  // get transformed type from specification
260  // Handling this transformation in a way that makes the per-node specification easy to write
261  // is a little involved:
262  // The problem is that the transformed power node must be parameterized on the transformed child
263  // type. So we need to transform the child type and pass the transformed child type to an inner
264  // template of the node transformation struct called result (see example of such a specification
265  // further down).
266  typedef typename LookupNodeTransformation<S,T,typename S::ImplementationTag>::type NodeTransformation;
267  typedef typename LookupNodeTransformation<typename S::ChildType,T,typename S::ChildType::ImplementationTag>::type ChildNodeTransformation;
268 
269  typedef typename NodeTransformation::template result<typename TransformTree<typename S::ChildType,
270  T,
271  typename S::ChildType::NodeTag,
272  ChildNodeTransformation::recursive>::transformed_type
273  >::type transformed_type;
274 
275  typedef typename NodeTransformation::template result<typename TransformTree<typename S::ChildType,
276  T,
277  typename S::ChildType::NodeTag,
278  ChildNodeTransformation::recursive>::transformed_type
279  >::storage_type transformed_storage_type;
280 
281  // Transform an instance of S.
282  static transformed_type transform(const S& s, T& t)
283  {
284  // transform children
285  typedef TransformTree<typename S::ChildType,T,typename S::ChildType::NodeTag,ChildNodeTransformation::recursive> ChildTreeTransformation;
286  typedef typename ChildTreeTransformation::transformed_type transformed_child;
287  const std::size_t child_count = S::CHILDREN;
288  array<shared_ptr<transformed_child>,child_count> children;
289  for (std::size_t k = 0; k < child_count; ++k) {
290  children[k] = ChildTreeTransformation::transform_storage(s.childStorage(k),t);
291  }
292  // transform node
293  return NodeTransformation::transform(s,t,children);
294  }
295 
296  static transformed_type transform(const S& s, const T& t)
297  {
298  // transform children
299  typedef TransformTree<typename S::ChildType,T,typename S::ChildType::NodeTag,ChildNodeTransformation::recursive> ChildTreeTransformation;
300  typedef typename ChildTreeTransformation::transformed_type transformed_child;
301  const std::size_t child_count = S::CHILDREN;
302  array<shared_ptr<transformed_child>,child_count> children;
303  for (std::size_t k = 0; k < child_count; ++k) {
304  children[k] = ChildTreeTransformation::transform_storage(s.childStorage(k),t);
305  }
306  // transform node
307  return NodeTransformation::transform(s,t,children);
308  }
309 
310  // Transform an instance of S.
311  static transformed_type transform(shared_ptr<const S> sp, T& t)
312  {
313  // transform children
314  typedef TransformTree<typename S::ChildType,T,typename S::ChildType::NodeTag,ChildNodeTransformation::recursive> ChildTreeTransformation;
315  typedef typename ChildTreeTransformation::transformed_type transformed_child;
316  const std::size_t child_count = S::CHILDREN;
317  array<shared_ptr<transformed_child>,child_count> children;
318  for (std::size_t k = 0; k < child_count; ++k) {
319  children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t);
320  }
321  // transform node
322  return NodeTransformation::transform(sp,t,children);
323  }
324 
325  static transformed_type transform(shared_ptr<const S> sp, const T& t)
326  {
327  // transform children
328  typedef TransformTree<typename S::ChildType,T,typename S::ChildType::NodeTag,ChildNodeTransformation::recursive> ChildTreeTransformation;
329  typedef typename ChildTreeTransformation::transformed_type transformed_child;
330  const std::size_t child_count = S::CHILDREN;
331  array<shared_ptr<transformed_child>,child_count> children;
332  for (std::size_t k = 0; k < child_count; ++k) {
333  children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t);
334  }
335  // transform node
336  return NodeTransformation::transform(sp,t,children);
337  }
338 
339  static transformed_storage_type transform_storage(shared_ptr<const S> sp, T& t)
340  {
341  // transform children
342  typedef TransformTree<typename S::ChildType,T,typename S::ChildType::NodeTag,ChildNodeTransformation::recursive> ChildTreeTransformation;
343  typedef typename ChildTreeTransformation::transformed_storage_type transformed_child_storage;
344  const std::size_t child_count = S::CHILDREN;
345  array<transformed_child_storage,child_count> children;
346  for (std::size_t k = 0; k < child_count; ++k) {
347  children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t);
348  }
349  return NodeTransformation::transform_storage(sp,t,children);
350  }
351 
352  static transformed_storage_type transform_storage(shared_ptr<const S> sp, const T& t)
353  {
354  // transform children
355  typedef TransformTree<typename S::ChildType,T,typename S::ChildType::NodeTag,ChildNodeTransformation::recursive> ChildTreeTransformation;
356  typedef typename ChildTreeTransformation::transformed_storage_type transformed_child_storage;
357  const std::size_t child_count = S::CHILDREN;
358  array<transformed_child_storage,child_count> children;
359  for (std::size_t k = 0; k < child_count; ++k) {
360  children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t);
361  }
362  return NodeTransformation::transform_storage(sp,t,children);
363  }
364 
365  };
366 
367  // non-recursive version of the PowerNode transformation.
368  template<typename S, typename T>
369  struct TransformTree<S,T,PowerNodeTag,false>
370  : public TransformTreeNonRecursive<S,T>
371  {};
372 
373 
374 
375  // non-variadic version
376 
377  // helper struct that does the actual transformation for a composite node. We need this additional struct
378  // to extract the template argument list with the types of all children from the node, which we cannot do
379  // directly in the transformation<> template, as the type passed to transformation<> will usually be a
380  // derived type and will normally have more template arguments than just the children. This declaration
381  // just introduces the type of the helper struct, we always instantiate the specialization defined below;
382  template<typename S, typename Children, typename T>
383  struct transform_composite_node;
384 
385 
386  // specialized version of the helper struct which extracts the template argument list with the children from
387  // its second template parameter, which has to be CompositeNode::ChildTypes. Apart from that, the struct is
388  // similar to the one for a PowerNode, but it obviously delegates transformation of the children to the TMP.
389  template<typename S, typename T, typename C0, typename C1, typename C2, typename C3, typename C4, typename C5, typename C6, typename C7, typename C8, typename C9>
390  struct transform_composite_node<S,tuple<C0,C1,C2,C3,C4,C5,C6,C7,C8,C9>,T>
391  {
392 
393  // transformed type, using the same nested struct trick as the PowerNode
394  typedef typename LookupNodeTransformation<S,T,typename S::ImplementationTag>::type NodeTransformation;
395 
396  typedef typename NodeTransformation::template result<
397  typename TransformTree<C0,T,typename C0::NodeTag,LookupNodeTransformation<C0,T,typename C0::ImplementationTag>::type::recursive>::transformed_type,
398  typename TransformTree<C1,T,typename C1::NodeTag,LookupNodeTransformation<C1,T,typename C1::ImplementationTag>::type::recursive>::transformed_type,
399  typename TransformTree<C2,T,typename C2::NodeTag,LookupNodeTransformation<C2,T,typename C2::ImplementationTag>::type::recursive>::transformed_type,
400  typename TransformTree<C3,T,typename C3::NodeTag,LookupNodeTransformation<C3,T,typename C3::ImplementationTag>::type::recursive>::transformed_type,
401  typename TransformTree<C4,T,typename C4::NodeTag,LookupNodeTransformation<C4,T,typename C4::ImplementationTag>::type::recursive>::transformed_type,
402  typename TransformTree<C5,T,typename C5::NodeTag,LookupNodeTransformation<C5,T,typename C5::ImplementationTag>::type::recursive>::transformed_type,
403  typename TransformTree<C6,T,typename C6::NodeTag,LookupNodeTransformation<C6,T,typename C6::ImplementationTag>::type::recursive>::transformed_type,
404  typename TransformTree<C7,T,typename C7::NodeTag,LookupNodeTransformation<C7,T,typename C7::ImplementationTag>::type::recursive>::transformed_type,
405  typename TransformTree<C8,T,typename C8::NodeTag,LookupNodeTransformation<C8,T,typename C8::ImplementationTag>::type::recursive>::transformed_type,
406  typename TransformTree<C9,T,typename C9::NodeTag,LookupNodeTransformation<C9,T,typename C9::ImplementationTag>::type::recursive>::transformed_type
407  > resulttypes;
408 
409  typedef typename resulttypes::type transformed_type;
410  typedef typename resulttypes::storage_type transformed_storage_type;
411  typedef typename S::ImplementationTag Tag;
412 
413  static transformed_type transform(const S& s, T& t)
414  {
415  return NodeTransformation::transform(s,
416  t,
417  TransformTree<C0,T,typename C0::NodeTag,LookupNodeTransformation<C0,T,typename C0::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<0>(),t),
418  TransformTree<C1,T,typename C1::NodeTag,LookupNodeTransformation<C1,T,typename C1::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<1>(),t),
419  TransformTree<C2,T,typename C2::NodeTag,LookupNodeTransformation<C2,T,typename C2::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<2>(),t),
420  TransformTree<C3,T,typename C3::NodeTag,LookupNodeTransformation<C3,T,typename C3::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<3>(),t),
421  TransformTree<C4,T,typename C4::NodeTag,LookupNodeTransformation<C4,T,typename C4::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<4>(),t),
422  TransformTree<C5,T,typename C5::NodeTag,LookupNodeTransformation<C5,T,typename C5::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<5>(),t),
423  TransformTree<C6,T,typename C6::NodeTag,LookupNodeTransformation<C6,T,typename C6::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<6>(),t),
424  TransformTree<C7,T,typename C7::NodeTag,LookupNodeTransformation<C7,T,typename C7::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<7>(),t),
425  TransformTree<C8,T,typename C8::NodeTag,LookupNodeTransformation<C8,T,typename C8::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<8>(),t),
426  TransformTree<C9,T,typename C9::NodeTag,LookupNodeTransformation<C9,T,typename C9::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<9>(),t));
427  }
428 
429  static transformed_type transform(const S& s, const T& t)
430  {
431  return NodeTransformation::transform(s,
432  t,
433  TransformTree<C0,T,typename C0::NodeTag,LookupNodeTransformation<C0,T,typename C0::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<0>(),t),
434  TransformTree<C1,T,typename C1::NodeTag,LookupNodeTransformation<C1,T,typename C1::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<1>(),t),
435  TransformTree<C2,T,typename C2::NodeTag,LookupNodeTransformation<C2,T,typename C2::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<2>(),t),
436  TransformTree<C3,T,typename C3::NodeTag,LookupNodeTransformation<C3,T,typename C3::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<3>(),t),
437  TransformTree<C4,T,typename C4::NodeTag,LookupNodeTransformation<C4,T,typename C4::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<4>(),t),
438  TransformTree<C5,T,typename C5::NodeTag,LookupNodeTransformation<C5,T,typename C5::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<5>(),t),
439  TransformTree<C6,T,typename C6::NodeTag,LookupNodeTransformation<C6,T,typename C6::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<6>(),t),
440  TransformTree<C7,T,typename C7::NodeTag,LookupNodeTransformation<C7,T,typename C7::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<7>(),t),
441  TransformTree<C8,T,typename C8::NodeTag,LookupNodeTransformation<C8,T,typename C8::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<8>(),t),
442  TransformTree<C9,T,typename C9::NodeTag,LookupNodeTransformation<C9,T,typename C9::ImplementationTag>::type::recursive>::transform_storage(s.template childStorage<9>(),t));
443  }
444 
445  static transformed_storage_type transform_storage(shared_ptr<const S> sp, T& t)
446  {
447  return NodeTransformation::transform_storage(sp,
448  t,
449  TransformTree<C0,T,typename C0::NodeTag,LookupNodeTransformation<C0,T,typename C0::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<0>(),t),
450  TransformTree<C1,T,typename C1::NodeTag,LookupNodeTransformation<C1,T,typename C1::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<1>(),t),
451  TransformTree<C2,T,typename C2::NodeTag,LookupNodeTransformation<C2,T,typename C2::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<2>(),t),
452  TransformTree<C3,T,typename C3::NodeTag,LookupNodeTransformation<C3,T,typename C3::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<3>(),t),
453  TransformTree<C4,T,typename C4::NodeTag,LookupNodeTransformation<C4,T,typename C4::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<4>(),t),
454  TransformTree<C5,T,typename C5::NodeTag,LookupNodeTransformation<C5,T,typename C5::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<5>(),t),
455  TransformTree<C6,T,typename C6::NodeTag,LookupNodeTransformation<C6,T,typename C6::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<6>(),t),
456  TransformTree<C7,T,typename C7::NodeTag,LookupNodeTransformation<C7,T,typename C7::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<7>(),t),
457  TransformTree<C8,T,typename C8::NodeTag,LookupNodeTransformation<C8,T,typename C8::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<8>(),t),
458  TransformTree<C9,T,typename C9::NodeTag,LookupNodeTransformation<C9,T,typename C9::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<9>(),t));
459  }
460 
461  static transformed_storage_type transform_storage(shared_ptr<const S> sp, const T& t)
462  {
463  return NodeTransformation::transform_storage(sp,
464  t,
465  TransformTree<C0,T,typename C0::NodeTag,LookupNodeTransformation<C0,T,typename C0::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<0>(),t),
466  TransformTree<C1,T,typename C1::NodeTag,LookupNodeTransformation<C1,T,typename C1::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<1>(),t),
467  TransformTree<C2,T,typename C2::NodeTag,LookupNodeTransformation<C2,T,typename C2::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<2>(),t),
468  TransformTree<C3,T,typename C3::NodeTag,LookupNodeTransformation<C3,T,typename C3::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<3>(),t),
469  TransformTree<C4,T,typename C4::NodeTag,LookupNodeTransformation<C4,T,typename C4::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<4>(),t),
470  TransformTree<C5,T,typename C5::NodeTag,LookupNodeTransformation<C5,T,typename C5::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<5>(),t),
471  TransformTree<C6,T,typename C6::NodeTag,LookupNodeTransformation<C6,T,typename C6::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<6>(),t),
472  TransformTree<C7,T,typename C7::NodeTag,LookupNodeTransformation<C7,T,typename C7::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<7>(),t),
473  TransformTree<C8,T,typename C8::NodeTag,LookupNodeTransformation<C8,T,typename C8::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<8>(),t),
474  TransformTree<C9,T,typename C9::NodeTag,LookupNodeTransformation<C9,T,typename C9::ImplementationTag>::type::recursive>::transform_storage(sp->template childStorage<9>(),t));
475  }
476  };
477 
478 
479  // the specialization of transformation<> for the CompositeNode. This just extracts the
480  // CompositeNode::ChildType member and forwards to the helper struct
481  template<typename S, typename T>
482  struct TransformTree<S,T,CompositeNodeTag,true>
483  {
484  typedef typename transform_composite_node<S,typename S::ChildTypes,T>::transformed_type transformed_type;
485  typedef typename transform_composite_node<S,typename S::ChildTypes,T>::transformed_storage_type transformed_storage_type;
486 
487  static transformed_type transform(const S& s, T& t)
488  {
489  return transform_composite_node<S,typename S::ChildTypes,T>::transform(s,t);
490  }
491 
492  static transformed_type transform(const S& s, const T& t)
493  {
494  return transform_composite_node<S,typename S::ChildTypes,T>::transform(s,t);
495  }
496 
497  static transformed_storage_type transform_storage(shared_ptr<const S> sp, T& t)
498  {
499  return transform_composite_node<S,typename S::ChildTypes,T>::transform_storage(sp,t);
500  }
501 
502  static transformed_storage_type transform_storage(shared_ptr<const S> sp, const T& t)
503  {
504  return transform_composite_node<S,typename S::ChildTypes,T>::transform_storage(sp,t);
505  }
506 
507  };
508 
509  // non-recursive version of the CompositeNode transformation.
510  template<typename S, typename T>
511  struct TransformTree<S,T,CompositeNodeTag,false>
512  : public TransformTreeNonRecursive<S,T>
513  {};
514 
515 #if HAVE_VARIADIC_TEMPLATES
516 
517  // helper struct that does the actual transformation for a composite node. We need this additional struct
518  // to extract the template argument list with the types of all children from the node, which we cannot do
519  // directly in the transformation<> template, as the type passed to transformation<> will usually be a
520  // derived type and will normally have more template arguments than just the children. This declaration
521  // just introduces the type of the helper struct, we always instantiate the specialization defined below;
522  template<typename S, typename Children, typename T>
523  struct transform_variadic_composite_node;
524 
525  // specialized version of the helper struct which extracts the template argument list with the children from
526  // its second template parameter, which has to be CompositeNode::ChildTypes. Apart from that, the struct is
527  // similar to the one for a PowerNode, but it obviously delegates transformation of the children to the TMP.
528  template<typename S, typename T, typename... C>
529  struct transform_variadic_composite_node<S,tuple<C...>,T>
530  {
531 
532  // transformed type, using the same nested struct trick as the PowerNode
533  typedef typename S::ImplementationTag Tag;
534  typedef typename LookupNodeTransformation<S,T,Tag>::type NodeTransformation;
535  typedef typename NodeTransformation::template result<typename TransformTree<C,
536  T,
537  typename C::NodeTag,
538  LookupNodeTransformation<C,T,typename C::ImplementationTag>::type::recursive
539  >::transformed_type...
540  >::type transformed_type;
541 
542  typedef typename NodeTransformation::template result<typename TransformTree<C,
543  T,
544  typename C::NodeTag,
545  LookupNodeTransformation<C,T,typename C::ImplementationTag>::type::recursive
546  >::transformed_type...
547  >::storage_type transformed_storage_type;
548 
549  // Retrieve the transformation descriptor for the child with index i.
550  // This little helper improves really improves the readability of the
551  // transformation functions.
552  template<std::size_t i>
553  struct ChildTransformation
554  : public TransformTree<typename S::template Child<i>::Type,
555  T,
556  typename S::template Child<i>::Type::NodeTag,
557  LookupNodeTransformation<
558  typename S::template Child<i>::Type,
559  T,
560  typename S::template Child<i>::Type::ImplementationTag
561  >::type::recursive
562  >
563  {};
564 
565 
566  template<std::size_t... i>
567  static transformed_type transform(const S& s, T& t, index_pack<i...> indices)
568  {
569  return NodeTransformation::transform(s,t,ChildTransformation<i>::transform_storage(s.template childStorage<i>(),t)...);
570  }
571 
572  template<std::size_t... i>
573  static transformed_type transform(const S& s, const T& t, index_pack<i...> indices)
574  {
575  return NodeTransformation::transform(s,t,ChildTransformation<i>::transform_storage(s.template childStorage<i>(),t)...);
576  }
577 
578  template<std::size_t... i>
579  static transformed_storage_type transform_storage(shared_ptr<const S> sp, T& t, index_pack<i...> indices)
580  {
581  return NodeTransformation::transform_storage(sp,t,ChildTransformation<i>::transform_storage(sp->template childStorage<i>(),t)...);
582  }
583 
584  template<std::size_t... i>
585  static transformed_storage_type transform_storage(shared_ptr<const S> sp, const T& t, index_pack<i...> indices)
586  {
587  return NodeTransformation::transform_storage(sp,t,ChildTransformation<i>::transform_storage(sp->template childStorage<i>(),t)...);
588  }
589 
590  };
591 
592 
593  // the specialization of transformation<> for the CompositeNode. This just extracts the
594  // CompositeNode::ChildTypes member and forwards to the helper struct
595  template<typename S, typename T>
596  struct TransformTree<S,T,VariadicCompositeNodeTag,true>
597  {
598 
599  private:
600 
601  typedef typename S::ChildTypes ChildTypes;
602 
603  static typename tuple_index_pack_builder<ChildTypes>::type child_indices()
604  {
605  return typename tuple_index_pack_builder<ChildTypes>::type();
606  }
607 
608  public:
609 
610  typedef typename transform_variadic_composite_node<S,ChildTypes,T>::transformed_type transformed_type;
611  typedef typename transform_variadic_composite_node<S,ChildTypes,T>::transformed_storage_type transformed_storage_type;
612 
613  static transformed_type transform(const S& s, T& t)
614  {
615  return transform_variadic_composite_node<S,ChildTypes,T>::transform(s,t,child_indices());
616  }
617 
618  static transformed_type transform(const S& s, const T& t)
619  {
620  return transform_variadic_composite_node<S,ChildTypes,T>::transform(s,t,child_indices());
621  }
622 
623  static transformed_storage_type transform_storage(shared_ptr<const S> sp, T& t)
624  {
625  return transform_variadic_composite_node<S,ChildTypes,T>::transform_storage(sp,t,child_indices());
626  }
627 
628  static transformed_storage_type transform_storage(shared_ptr<const S> sp, const T& t)
629  {
630  return transform_variadic_composite_node<S,ChildTypes,T>::transform_storage(sp,t,child_indices());
631  }
632 
633  };
634 
635  // non-recursive version of the VariadicCompositeNode transformation.
636  template<typename S, typename T>
637  struct TransformTree<S,T,VariadicCompositeNodeTag,false>
638  : public TransformTreeNonRecursive<S,T>
639  {};
640 
641 
642 #endif // HAVE_VARIADIC_TEMPLATES
643 
644  // generic transformation descriptor for empty nodes
645  struct EmptyNodeTransformation
646  {
647  // there is nothing to recurse into here
648  static const bool recursive = false;
649  };
650 
651  // handle empty nodes
652  template<typename T, bool recursive>
653  struct TransformTree<EmptyNode,T,EmptyNodeTag,recursive>
654  {
655  // get transformed type from specification
656  typedef EmptyNode transformed_type;
657  typedef shared_ptr<EmptyNode> transformed_storage_type;
658 
659  // delegate instance transformation to per-node specification
660  static transformed_type transform(const EmptyNode& s, const T& t)
661  {
662  DUNE_THROW(NotImplemented,"this should never get called!");
663  }
664 
665  static transformed_storage_type transform_storage(shared_ptr<const EmptyNode> en, const T& t)
666  {
667  //return const_pointer_cast<transformed_type>(en); // Dune built-in shared_ptr does not support this!
668  return emptyNodePtr();
669  }
670  };
671 
672 #endif // DOXYGEN
673 
675 
676  } // namespace TypeTree
677 } //namespace Dune
678 
679 #endif // DUNE_TYPETREE_TRANSFORMATION_HH
static transformed_storage_type transform_storage(shared_ptr< const SourceTree > sp, const Transformation &t=Transformation())
Definition: transformation.hh:144
Transform a TypeTree.
Definition: transformation.hh:99
void registerNodeTransformation(SourceNode *, Transformation *, Tag *)
Register transformation descriptor to transform SourceNode with Transformation.
static transformed_type transform(shared_ptr< const SourceTree > sp, Transformation &t)
Apply transformation to an existing tree s.
Definition: transformation.hh:137
const shared_ptr< EmptyNode > & emptyNodePtr()
Reference to a pointer to an empty node that is used for all empty slots.
Definition: utility.cc:12
static const result_type result
Definition: accumulate_static.hh:108
static transformed_storage_type transform_storage(shared_ptr< const SourceTree > sp, Transformation &t)
Definition: transformation.hh:151
static transformed_type transform(shared_ptr< const SourceTree > sp, const Transformation &t=Transformation())
Apply transformation to an existing tree s.
Definition: transformation.hh:131
static transformed_type transform(const SourceTree &s, Transformation &t)
Apply transformation to an existing tree s.
Definition: transformation.hh:125
static const std::size_t value
Definition: compositenode.hh:38
static transformed_type transform(const SourceTree &s, const Transformation &t=Transformation())
Apply transformation to an existing tree s.
Definition: transformation.hh:119
transformed_type Type
The type of the transformed tree.
Definition: transformation.hh:115