dune-typetree  2.7.1
pairtraversal.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_PAIRTRAVERSAL_HH
5 #define DUNE_TYPETREE_PAIRTRAVERSAL_HH
6 
7 #include <dune/common/std/type_traits.hh>
8 
12 #include <dune/typetree/visitor.hh>
14 
15 namespace Dune {
16  namespace TypeTree {
17 
23  namespace Detail {
24 
25  /* The signature is the same as for the public applyToTreePair
26  * function in Dune::Typtree, despite the additionally passed
27  * treePath argument. The path passed here is associated to
28  * the tree and the relative paths of the children (wrt. to tree)
29  * are appended to this. Hence the behavior of the public function
30  * is resembled by passing an empty treePath.
31  */
32 
33  /*
34  * This is the overload for leaf traversal
35  */
36  template<class T1, class T2, class TreePath, class V,
37  std::enable_if_t<(std::decay_t<T1>::isLeaf or std::decay_t<T2>::isLeaf), int> = 0>
38  void applyToTreePair(T1&& tree1, T2&& tree2, TreePath treePath, V&& visitor)
39  {
40  visitor.leaf(tree1, tree2, treePath);
41  }
42 
43  /*
44  * This is the general overload doing static child traversal.
45  */
46  template<class T1, class T2, class TreePath, class V,
47  std::enable_if_t<not(std::decay_t<T1>::isLeaf or std::decay_t<T2>::isLeaf), int> = 0>
48  void applyToTreePair(T1&& tree1, T2&& tree2, TreePath treePath, V&& visitor)
49  {
50  // Do we really want to take care for const-ness of the Tree
51  // when instanciating VisitChild below? I'd rather expect this:
52  // using Tree1 = std::decay_t<T1>;
53  // using Tree2 = std::decay_t<T2>;
54  // using Visitor = std::decay_t<V>;
55  using Tree1 = std::remove_reference_t<T1>;
56  using Tree2 = std::remove_reference_t<T2>;
57  using Visitor = std::remove_reference_t<V>;
58  visitor.pre(tree1, tree2, treePath);
59 
60  // Use statically encoded degree unless both trees
61  // are power nodes and dynamic traversal is requested.
62  constexpr auto useDynamicTraversal = (Tree1::isPower and Tree2::isPower and Visitor::treePathType==TreePathType::dynamic);
63  auto degree = conditionalValue<useDynamicTraversal>(Tree1::degree(), Dune::index_constant<Tree1::degree()>{});
64 
65  auto indices = Dune::range(degree);
66  Dune::Hybrid::forEach(indices, [&](auto i) {
67  auto childTreePath = Dune::TypeTree::push_back(treePath, i);
68  auto&& child1 = tree1.child(i);
69  auto&& child2 = tree2.child(i);
70  using Child1 = std::decay_t<decltype(child1)>;
71  using Child2 = std::decay_t<decltype(child2)>;
72 
73  visitor.beforeChild(tree1, child1, tree2, child2, treePath, i);
74 
75  // This requires that visiotor.in(...) can always be instantiated,
76  // even if there's a single child only.
77  if (i>0)
78  visitor.in(tree1, tree2, treePath);
79  static const auto visitChild = Visitor::template VisitChild<Tree1,Child1,Tree2,Child2,TreePath>::value;
80  Dune::Hybrid::ifElse(Dune::Std::bool_constant<visitChild>{}, [&] (auto id) {
81  applyToTreePair(child1, child2, childTreePath, visitor);
82  });
83 
84  visitor.afterChild(tree1, child1, tree2, child2, treePath, i);
85  });
86  visitor.post(tree1, tree2, treePath);
87  }
88 
89  } // namespace Detail
90 
92 
106  template<typename Tree1, typename Tree2, typename Visitor>
107  void applyToTreePair(Tree1&& tree1, Tree2&& tree2, Visitor&& visitor)
108  {
109  Detail::applyToTreePair(tree1, tree2, hybridTreePath(), visitor);
110  }
111 
113 
114  } // namespace TypeTree
115 } //namespace Dune
116 
117 #endif // DUNE_TYPETREE_PAIRTRAVERSAL_HH
static const TreePathType::Type treePathType
Definition: traversalutilities.hh:30
void applyToTreePair(Tree1 &&tree1, Tree2 &&tree2, Visitor &&visitor)
Apply visitor to a pair of TypeTrees.
Definition: pairtraversal.hh:107
std::size_t degree(const Node &node)
Returns the degree of node as run time information.
Definition: nodeinterface.hh:71
constexpr HybridTreePath< T... > treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:188
constexpr HybridTreePath< T... > hybridTreePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:177
constexpr HybridTreePath< T..., std::size_t > push_back(const HybridTreePath< T... > &tp, std::size_t i)
Appends a run time index to a HybridTreePath.
Definition: treepath.hh:278
HybridTreePath< Dune::index_constant< i >... > TreePath
Definition: treepath.hh:433
Definition: accumulate_static.hh:13
void applyToTreePair(T1 &&tree1, T2 &&tree2, TreePath treePath, V &&visitor)
Definition: pairtraversal.hh:38
@ dynamic
Definition: treepath.hh:30
A hybrid version of TreePath that supports both compile time and run time indices.
Definition: treepath.hh:79