4 #ifndef DUNE_TYPETREE_TRANSFORMATION_HH
5 #define DUNE_TYPETREE_TRANSFORMATION_HH
12 #include <dune/common/exceptions.hh>
13 #include <dune/common/typetraits.hh>
50 template<
typename SourceNode,
typename Transformation,
typename Tag>
65 template<
typename S,
typename T,
typename Tag>
66 struct LookupNodeTransformation
71 typedef typename evaluate_if_meta_function<
75 static_assert((!std::is_same<type,
void>::value), "Unable to find valid transformation descriptor");
91 template<
typename SourceTree,
typename Transformation,
typename Tag = StartTag,
bool recursive = true>
97 typedef typename LookupNodeTransformation<SourceTree,Transformation,typename SourceTree::ImplementationTag>::type NodeTransformation;
113 static transformed_type
transform(
const SourceTree& s,
const Transformation& t = Transformation())
119 static transformed_type
transform(
const SourceTree& s, Transformation& t)
125 static transformed_type
transform(std::shared_ptr<const SourceTree> sp,
const Transformation& t = Transformation())
131 static transformed_type
transform(std::shared_ptr<const SourceTree> sp, Transformation& t)
138 static transformed_storage_type
transform_storage(std::shared_ptr<const SourceTree> sp,
const Transformation& t = Transformation())
145 static transformed_storage_type
transform_storage(std::shared_ptr<const SourceTree> sp, Transformation& t)
153 #ifndef DOXYGEN // internal per-node implementations of the transformation algorithm
156 template<
typename S,
typename T,
bool recursive>
157 struct TransformTree<S,T,LeafNodeTag,recursive>
160 typedef typename LookupNodeTransformation<S,T,ImplementationTag<S>>::type NodeTransformation;
162 typedef typename NodeTransformation::transformed_type transformed_type;
163 typedef typename NodeTransformation::transformed_storage_type transformed_storage_type;
166 static transformed_type transform(
const S& s, T& t)
168 return NodeTransformation::transform(s,t);
172 static transformed_type transform(
const S& s,
const T& t)
174 return NodeTransformation::transform(s,t);
178 static transformed_type transform(std::shared_ptr<const S> sp, T& t)
180 return NodeTransformation::transform(sp,t);
184 static transformed_type transform(std::shared_ptr<const S> sp,
const T& t)
186 return NodeTransformation::transform(sp,t);
189 static transformed_storage_type transform_storage(std::shared_ptr<const S> sp, T& t)
191 return NodeTransformation::transform_storage(sp,t);
194 static transformed_storage_type transform_storage(std::shared_ptr<const S> sp,
const T& t)
196 return NodeTransformation::transform_storage(sp,t);
203 template<
typename S,
typename T>
204 struct TransformTreeNonRecursive
207 typedef typename LookupNodeTransformation<S,T,ImplementationTag<S>>::type NodeTransformation;
209 typedef typename NodeTransformation::transformed_type transformed_type;
210 typedef typename NodeTransformation::transformed_storage_type transformed_storage_type;
213 static transformed_type transform(
const S& s, T& t)
215 return NodeTransformation::transform(s,t);
219 static transformed_type transform(
const S& s,
const T& t)
221 return NodeTransformation::transform(s,t);
225 static transformed_type transform(std::shared_ptr<const S> sp, T& t)
227 return NodeTransformation::transform(sp,t);
231 static transformed_type transform(std::shared_ptr<const S> sp,
const T& t)
233 return NodeTransformation::transform(sp,t);
236 static transformed_storage_type transform_storage(std::shared_ptr<const S> sp, T& t)
238 return NodeTransformation::transform_storage(sp,t);
241 static transformed_storage_type transform_storage(std::shared_ptr<const S> sp,
const T& t)
243 return NodeTransformation::transform_storage(sp,t);
250 template<
typename S,
typename T>
251 struct TransformTree<S,T,PowerNodeTag,true>
260 typedef typename LookupNodeTransformation<S,T,ImplementationTag<S>>::type NodeTransformation;
261 typedef typename LookupNodeTransformation<typename S::ChildType,T,ImplementationTag<typename S::ChildType>>::type ChildNodeTransformation;
263 typedef typename NodeTransformation::template
result<
typename TransformTree<
typename S::ChildType,
265 NodeTag<typename S::ChildType>,
266 ChildNodeTransformation::recursive>::transformed_type
267 >::type transformed_type;
269 typedef typename NodeTransformation::template
result<
typename TransformTree<
typename S::ChildType,
271 NodeTag<typename S::ChildType>,
272 ChildNodeTransformation::recursive>::transformed_type
273 >::storage_type transformed_storage_type;
276 static transformed_type transform(
const S& s, T& t)
279 typedef TransformTree<typename S::ChildType,T,NodeTag<typename S::ChildType>,ChildNodeTransformation::recursive> ChildTreeTransformation;
280 typedef typename ChildTreeTransformation::transformed_type transformed_child;
281 const std::size_t child_count = StaticDegree<S>::value;
282 std::array<std::shared_ptr<transformed_child>,child_count> children;
283 for (std::size_t k = 0; k < child_count; ++k) {
284 children[k] = ChildTreeTransformation::transform_storage(s.childStorage(k),t);
287 return NodeTransformation::transform(s,t,children);
290 static transformed_type transform(
const S& s,
const T& t)
293 typedef TransformTree<typename S::ChildType,T,NodeTag<typename S::ChildType>,ChildNodeTransformation::recursive> ChildTreeTransformation;
294 typedef typename ChildTreeTransformation::transformed_type transformed_child;
295 const std::size_t child_count = StaticDegree<S>::value;
296 std::array<std::shared_ptr<transformed_child>,child_count> children;
297 for (std::size_t k = 0; k < child_count; ++k) {
298 children[k] = ChildTreeTransformation::transform_storage(s.childStorage(k),t);
301 return NodeTransformation::transform(s,t,children);
305 static transformed_type transform(std::shared_ptr<const S> sp, T& t)
308 typedef TransformTree<typename S::ChildType,T,NodeTag<typename S::ChildType>,ChildNodeTransformation::recursive> ChildTreeTransformation;
309 typedef typename ChildTreeTransformation::transformed_type transformed_child;
310 const std::size_t child_count = StaticDegree<S>::value;
311 std::array<std::shared_ptr<transformed_child>,child_count> children;
312 for (std::size_t k = 0; k < child_count; ++k) {
313 children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t);
316 return NodeTransformation::transform(sp,t,children);
319 static transformed_type transform(std::shared_ptr<const S> sp,
const T& t)
322 typedef TransformTree<typename S::ChildType,T,NodeTag<typename S::ChildType>,ChildNodeTransformation::recursive> ChildTreeTransformation;
323 typedef typename ChildTreeTransformation::transformed_type transformed_child;
324 const std::size_t child_count = StaticDegree<S>::value;
325 std::array<std::shared_ptr<transformed_child>,child_count> children;
326 for (std::size_t k = 0; k < child_count; ++k) {
327 children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t);
330 return NodeTransformation::transform(sp,t,children);
333 static transformed_storage_type transform_storage(std::shared_ptr<const S> sp, T& t)
336 typedef TransformTree<typename S::ChildType,T,NodeTag<typename S::ChildType>,ChildNodeTransformation::recursive> ChildTreeTransformation;
337 typedef typename ChildTreeTransformation::transformed_storage_type transformed_child_storage;
338 const std::size_t child_count = StaticDegree<S>::value;
339 std::array<transformed_child_storage,child_count> children;
340 for (std::size_t k = 0; k < child_count; ++k) {
341 children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t);
343 return NodeTransformation::transform_storage(sp,t,children);
346 static transformed_storage_type transform_storage(std::shared_ptr<const S> sp,
const T& t)
349 typedef TransformTree<typename S::ChildType,T,NodeTag<typename S::ChildType>,ChildNodeTransformation::recursive> ChildTreeTransformation;
350 typedef typename ChildTreeTransformation::transformed_storage_type transformed_child_storage;
351 const std::size_t child_count = StaticDegree<S>::value;
352 std::array<transformed_child_storage,child_count> children;
353 for (std::size_t k = 0; k < child_count; ++k) {
354 children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t);
356 return NodeTransformation::transform_storage(sp,t,children);
362 template<
typename S,
typename T>
363 struct TransformTree<S,T,PowerNodeTag,false>
364 :
public TransformTreeNonRecursive<S,T>
372 template<
typename S,
typename Children,
typename T>
373 struct transform_composite_node;
378 template<
typename S,
typename T,
typename... C>
379 struct transform_composite_node<S,std::tuple<C...>,T>
383 typedef ImplementationTag<S> Tag;
384 typedef typename LookupNodeTransformation<S,T,Tag>::type NodeTransformation;
385 typedef typename NodeTransformation::template
result<
typename TransformTree<C,
388 LookupNodeTransformation<C,T,ImplementationTag<C>>::type::recursive
389 >::transformed_type...
390 >::type transformed_type;
392 typedef typename NodeTransformation::template
result<
typename TransformTree<C,
395 LookupNodeTransformation<C,T,ImplementationTag<C>>::type::recursive
396 >::transformed_type...
397 >::storage_type transformed_storage_type;
402 template<std::
size_t i>
403 struct ChildTransformation
404 :
public TransformTree<typename S::template Child<i>::Type,
406 NodeTag<typename S::template Child<i>::Type>,
407 LookupNodeTransformation<
408 typename S::template Child<i>::Type,
410 ImplementationTag<typename S::template Child<i>::Type>
415 template<std::
size_t i,
typename Tuple,
typename Value>
416 static void setElement(Tuple& tuple, Value&& value)
418 std::get<i>(tuple) = std::forward<Value>(value);
421 template<
typename Trafo, std::size_t... i>
422 static transformed_type transform(
const S& s, Trafo&& t, std::index_sequence<i...> indices)
424 std::tuple<typename ChildTransformation<i>::transformed_storage_type...> storage;
425 std::initializer_list<int>{(setElement<i>(storage, ChildTransformation<i>::transform_storage(s.template childStorage<i>(), std::forward<Trafo>(t))),0)...};
426 return NodeTransformation::transform(s, std::forward<Trafo>(t), std::get<i>(storage)...);
429 template<
typename Trafo, std::size_t... i>
430 static transformed_storage_type transform_storage(std::shared_ptr<const S> sp, Trafo&& t, std::index_sequence<i...> indices)
432 std::tuple<typename ChildTransformation<i>::transformed_storage_type...> storage;
433 std::initializer_list<int>{(setElement<i>(storage, ChildTransformation<i>::transform_storage(sp->template childStorage<i>(), std::forward<Trafo>(t))),0)...};
434 return NodeTransformation::transform_storage(sp, std::forward<Trafo>(t), std::get<i>(storage)...);
441 template<
typename S,
typename T>
442 struct TransformTree<S,T,CompositeNodeTag,true>
447 typedef typename S::ChildTypes ChildTypes;
449 static auto child_indices()
451 return std::make_index_sequence<S::CHILDREN>();
456 typedef typename transform_composite_node<S,ChildTypes,T>::transformed_type transformed_type;
457 typedef typename transform_composite_node<S,ChildTypes,T>::transformed_storage_type transformed_storage_type;
459 static transformed_type transform(
const S& s, T& t)
461 return transform_composite_node<S,ChildTypes,T>::transform(s,t,child_indices());
464 static transformed_type transform(
const S& s,
const T& t)
466 return transform_composite_node<S,ChildTypes,T>::transform(s,t,child_indices());
469 static transformed_storage_type transform_storage(std::shared_ptr<const S> sp, T& t)
471 return transform_composite_node<S,ChildTypes,T>::transform_storage(sp,t,child_indices());
474 static transformed_storage_type transform_storage(std::shared_ptr<const S> sp,
const T& t)
476 return transform_composite_node<S,ChildTypes,T>::transform_storage(sp,t,child_indices());
482 template<
typename S,
typename T>
483 struct TransformTree<S,T,CompositeNodeTag,false>
484 :
public TransformTreeNonRecursive<S,T>
494 #endif // DUNE_TYPETREE_TRANSFORMATION_HH