"Fossies" - the Fresh Open Source Software Archive 
Member "dune-typetree-2.8.0/dune/typetree/pairtraversal.hh" (31 Aug 2021, 5566 Bytes) of package /linux/misc/dune/dune-typetree-2.8.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "pairtraversal.hh" see the
Fossies "Dox" file reference documentation.
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
9 #include <dune/typetree/nodeinterface.hh>
10 #include <dune/typetree/nodetags.hh>
11 #include <dune/typetree/treepath.hh>
12 #include <dune/typetree/visitor.hh>
13 #include <dune/typetree/traversal.hh>
14
15 namespace Dune {
16 namespace TypeTree {
17
18 /** \addtogroup Tree Traversal
19 * \ingroup TypeTree
20 * \{
21 */
22
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 // check which type of traversal is supported by the trees
61 using allowDynamicTraversal = std::conjunction<
62 Dune::Std::is_detected<DynamicTraversalConcept,Tree1>,
63 Dune::Std::is_detected<DynamicTraversalConcept,Tree2>>;
64 using allowStaticTraversal = std::conjunction<
65 Dune::Std::is_detected<StaticTraversalConcept,Tree1>,
66 Dune::Std::is_detected<StaticTraversalConcept,Tree2>>;
67
68 // both trees must support either dynamic or static traversal
69 static_assert(allowDynamicTraversal::value || allowStaticTraversal::value);
70
71 // the visitor may specify preferred dynamic traversal
72 using preferDynamicTraversal = std::bool_constant<Visitor::treePathType == TreePathType::dynamic>;
73
74 // create a dynamic or static index range
75 auto indices = [&]{
76 if constexpr(preferDynamicTraversal::value && allowDynamicTraversal::value)
77 return Dune::range(std::size_t(tree1.degree()));
78 else
79 return Dune::range(tree1.degree());
80 }();
81
82 if constexpr(allowDynamicTraversal::value || allowStaticTraversal::value) {
83 Dune::Hybrid::forEach(indices, [&](auto i) {
84 auto&& child1 = tree1.child(i);
85 auto&& child2 = tree2.child(i);
86 using Child1 = std::decay_t<decltype(child1)>;
87 using Child2 = std::decay_t<decltype(child2)>;
88
89 visitor.beforeChild(tree1, child1, tree2, child2, treePath, i);
90
91 // This requires that visitor.in(...) can always be instantiated,
92 // even if there's a single child only.
93 if (i>0)
94 visitor.in(tree1, tree2, treePath);
95
96 constexpr bool visitChild = Visitor::template VisitChild<Tree1,Child1,Tree2,Child2,TreePath>::value;
97 if constexpr(visitChild) {
98 auto childTreePath = Dune::TypeTree::push_back(treePath, i);
99 applyToTreePair(child1, child2, childTreePath, visitor);
100 }
101
102 visitor.afterChild(tree1, child1, tree2, child2, treePath, i);
103 });
104 }
105 visitor.post(tree1, tree2, treePath);
106 }
107
108 } // namespace Detail
109
110 //! Apply visitor to a pair of TypeTrees.
111 /**
112 * This function applies the given visitor to the given tree. Both visitor and tree may be const
113 * or non-const. If the compiler supports rvalue references, they may even be a non-const temporary;
114 * otherwise both trees must be either const or non-const. If they have different constness, both will
115 * be promoted to const.
116 *
117 * \note The visitor must implement the interface laid out by DefaultPairVisitor (most easily achieved by
118 * inheriting from it) and specify the required type of tree traversal (static or dynamic) by
119 * inheriting from either StaticTraversal or DynamicTraversal.
120 *
121 * \param tree1 The first tree the visitor will be applied to.
122 * \param tree2 The second tree the visitor will be applied to.
123 * \param visitor The visitor to apply to the trees.
124 */
125 template<typename Tree1, typename Tree2, typename Visitor>
126 void applyToTreePair(Tree1&& tree1, Tree2&& tree2, Visitor&& visitor)
127 {
128 Detail::applyToTreePair(tree1, tree2, hybridTreePath(), visitor);
129 }
130
131 //! \} group Tree Traversal
132
133 } // namespace TypeTree
134 } //namespace Dune
135
136 #endif // DUNE_TYPETREE_PAIRTRAVERSAL_HH