Dune TypeTree (unstable)

traversal.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-GPL-2.0-only-with-PDELab-exception
5
6#ifndef DUNE_TYPETREE_TRAVERSAL_HH
7#define DUNE_TYPETREE_TRAVERSAL_HH
8
9#include <utility>
10
11#include <dune/common/hybridutilities.hh>
12#include <dune/common/indices.hh>
13#include <dune/common/std/type_traits.hh>
14
15#include <dune/common/typetree/childaccess.hh>
16#include <dune/common/typetree/nodeconcepts.hh>
17#include <dune/common/typetree/traversal.hh>
18
19#include <dune/typetree/treepath.hh>
20#include <dune/typetree/visitor.hh>
21
22namespace Dune {
23 namespace TypeTree {
24
30 namespace Detail {
31
32 // SFINAE template check that Tree has a degree() function and a child() function accepting integer indices
33 template<class Tree>
34 using DynamicTraversalConcept = decltype((
35 std::declval<Tree>().degree(),
36 std::declval<Tree>().child(0u)
37 ));
38
39 // SFINAE template check that Tree has static (constexpr) function Tree::degree()
40 template<class Tree>
41 using StaticTraversalConcept = decltype((
42 std::integral_constant<std::size_t, Tree::degree()>{}
43 ));
44
45
46 template<class Tree, TreePathType::Type pathType, class Prefix,
47 std::enable_if_t<Tree::isLeaf, int> = 0>
48 constexpr auto leafTreePathTuple(Prefix prefix)
49 {
50 return std::make_tuple(prefix);
51 }
52
53 template<class Tree, TreePathType::Type pathType, class Prefix,
54 std::enable_if_t<not Tree::isLeaf, int> = 0>
55 constexpr auto leafTreePathTuple(Prefix prefix);
56
57 template<class Tree, TreePathType::Type pathType, class Prefix, std::size_t... indices,
58 std::enable_if_t<(Tree::isComposite or (Tree::isPower and (pathType!=TreePathType::dynamic))), int> = 0>
59 constexpr auto leafTreePathTuple(Prefix prefix, std::index_sequence<indices...>)
60 {
61 return std::tuple_cat(Detail::leafTreePathTuple<TypeTree::Child<Tree,indices>, pathType>(Dune::TypeTree::push_back(prefix, Dune::index_constant<indices>{}))...);
62 }
63
64 template<class Tree, TreePathType::Type pathType, class Prefix, std::size_t... indices,
65 std::enable_if_t<(Tree::isPower and (pathType==TreePathType::dynamic)), int> = 0>
66 constexpr auto leafTreePathTuple(Prefix prefix, std::index_sequence<indices...>)
67 {
68 return std::tuple_cat(Detail::leafTreePathTuple<TypeTree::Child<Tree,indices>, pathType>(Dune::TypeTree::push_back(prefix, indices))...);
69 }
70
71 template<class Tree, TreePathType::Type pathType, class Prefix,
72 std::enable_if_t<not Tree::isLeaf, int>>
73 constexpr auto leafTreePathTuple(Prefix prefix)
74 {
75 return Detail::leafTreePathTuple<Tree, pathType>(prefix, std::make_index_sequence<Tree::degree()>{});
76 }
77
78 /* The signature is the same as for the public applyToTree
79 * function in Dune::Typetree, despite the additionally passed
80 * treePath argument. The path passed here is associated to
81 * the tree and the relative paths of the children (wrt. to tree)
82 * are appended to this. Hence the behavior of the public function
83 * is resembled by passing an empty treePath.
84 */
85
86 /*
87 * This is the overload for leaf traversal
88 */
89 template<class T, class TreePath, class V,
90 std::enable_if_t<std::decay_t<T>::isLeaf, int> = 0>
91 void applyToTree(T&& tree, TreePath treePath, V&& visitor)
92 {
93 visitor.leaf(tree, treePath);
94 }
95
96 /*
97 * This is the general overload doing child traversal.
98 */
99 template<class T, class TreePath, class V,
100 std::enable_if_t<not std::decay_t<T>::isLeaf, int> = 0>
101 void applyToTree(T&& tree, TreePath treePath, V&& visitor)
102 {
103 using Tree = std::remove_reference_t<T>;
104 using Visitor = std::remove_reference_t<V>;
105 visitor.pre(tree, treePath);
106
107 // the visitor may specify preferred dynamic traversal
108 using preferDynamicTraversal = std::bool_constant<Visitor::treePathType == TreePathType::dynamic>;
109
110 // create a dynamic or static index range
111 auto indices = [&]{
112 if constexpr(preferDynamicTraversal::value && Concept::UniformInnerTreeNode<Tree>)
113 return Dune::range(std::size_t(tree.degree()));
114 else
115 return Dune::range(tree.degree());
116 }();
117
118 if constexpr(Concept::InnerTreeNode<Tree>) {
119 Hybrid::forEach(indices, [&](auto i) {
120 auto&& child = tree.child(i);
121 using Child = std::decay_t<decltype(child)>;
122
123 visitor.beforeChild(tree, child, treePath, i);
124
125 // This requires that visitor.in(...) can always be instantiated,
126 // even if there's a single child only.
127 if (i>0)
128 visitor.in(tree, treePath);
129
130 constexpr bool visitChild = Visitor::template VisitChild<Tree,Child,TreePath>::value;
131 if constexpr(visitChild) {
132 auto childTreePath = Dune::TypeTree::push_back(treePath, i);
133 applyToTree(child, childTreePath, visitor);
134 }
135
136 visitor.afterChild(tree, child, treePath, i);
137 });
138 }
139 visitor.post(tree, treePath);
140 }
141
142 } // namespace Detail
143
144
145 // ********************************************************************************
146 // Public Interface
147 // ********************************************************************************
148
162 template<class Tree, TreePathType::Type pathType=TreePathType::dynamic>
163 constexpr auto leafTreePathTuple()
164 {
165 return Detail::leafTreePathTuple<std::decay_t<Tree>, pathType>(hybridTreePath());
166 }
167
169
183 template<Concept::TreeNode Tree, typename Visitor>
184 void applyToTree(Tree&& tree, Visitor&& visitor)
185 {
186 Detail::applyToTree(tree, hybridTreePath(), visitor);
187 }
188
190
191 } // namespace TypeTree
192} //namespace Dune
193
194#endif // DUNE_TYPETREE_TRAVERSAL_HH
std::size_t degree(const Node &node)
Returns the degree of node as run time information.
Definition: nodeinterface.hh:79
constexpr auto hybridTreePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:102
constexpr auto leafTreePathTuple()
Create tuple of tree paths to leafs.
Definition: traversal.hh:163
void applyToTree(Tree &&tree, Visitor &&visitor)
Apply visitor to TypeTree.
Definition: traversal.hh:184
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Jan 10, 23:35, 2026)