6#ifndef DUNE_TYPETREE_TRAVERSAL_HH
7#define DUNE_TYPETREE_TRAVERSAL_HH
11#include <dune/common/hybridutilities.hh>
12#include <dune/common/std/type_traits.hh>
14#include <dune/typetree/childextraction.hh>
15#include <dune/typetree/treepath.hh>
16#include <dune/typetree/visitor.hh>
31 constexpr void operator()(T&&...)
const { }
39 using DynamicTraversalConcept =
decltype((
40 std::declval<Tree>().degree(),
41 std::declval<Tree>().child(0u)
46 using StaticTraversalConcept =
decltype((
51 template<
class Tree, TreePathType::Type pathType,
class Prefix,
52 std::enable_if_t<Tree::isLeaf, int> = 0>
55 return std::make_tuple(prefix);
58 template<
class Tree, TreePathType::Type pathType,
class Prefix,
59 std::enable_if_t<not Tree::isLeaf, int> = 0>
62 template<
class Tree, TreePathType::Type pathType,
class Prefix, std::size_t... indices,
63 std::enable_if_t<(Tree::isComposite or (Tree::isPower and (pathType!=TreePathType::dynamic))),
int> = 0>
66 return std::tuple_cat(
Detail::leafTreePathTuple<TypeTree::Child<Tree,indices>, pathType>(Dune::TypeTree::push_back(prefix, Dune::index_constant<indices>{}))...);
69 template<
class Tree, TreePathType::Type pathType,
class Prefix, std::size_t... indices,
70 std::enable_if_t<(Tree::isPower and (pathType==TreePathType::dynamic)),
int> = 0>
73 return std::tuple_cat(
Detail::leafTreePathTuple<TypeTree::Child<Tree,indices>, pathType>(Dune::TypeTree::push_back(prefix, indices))...);
76 template<
class Tree, TreePathType::Type pathType,
class Prefix,
77 std::enable_if_t<not Tree::isLeaf, int>>
80 return Detail::leafTreePathTuple<Tree, pathType>(prefix, std::make_index_sequence<
Tree::degree()>{});
94 template<
class T,
class TreePath,
class V,
95 std::enable_if_t<std::decay_t<T>::isLeaf,
int> = 0>
104 template<
class T,
class TreePath,
class V,
105 std::enable_if_t<not std::decay_t<T>::isLeaf,
int> = 0>
108 using Tree = std::remove_reference_t<T>;
109 using Visitor = std::remove_reference_t<V>;
113 using allowDynamicTraversal = Dune::Std::is_detected<DynamicTraversalConcept,Tree>;
114 using allowStaticTraversal = Dune::Std::is_detected<StaticTraversalConcept,Tree>;
117 static_assert(allowDynamicTraversal::value || allowStaticTraversal::value);
120 using preferDynamicTraversal = std::bool_constant<Visitor::treePathType == TreePathType::dynamic>;
124 if constexpr(preferDynamicTraversal::value && allowDynamicTraversal::value)
125 return Dune::range(std::size_t(tree.degree()));
127 return Dune::range(tree.degree());
130 if constexpr(allowDynamicTraversal::value || allowStaticTraversal::value) {
131 Hybrid::forEach(indices, [&](
auto i) {
132 auto&&
child = tree.child(i);
142 constexpr bool visitChild = Visitor::template VisitChild<Tree,Child,TreePath>::value;
143 if constexpr(visitChild) {
144 auto childTreePath = Dune::TypeTree::push_back(
treePath, i);
162 template<
class T,
class TreePath,
class PreFunc,
class LeafFunc,
class PostFunc>
163 void forEachNode(T&& tree, TreePath
treePath, PreFunc&& preFunc, LeafFunc&& leafFunc, PostFunc&& postFunc)
165 using Tree = std::decay_t<T>;
166 if constexpr(Tree::isLeaf) {
172 using allowDynamicTraversal = Dune::Std::is_detected<DynamicTraversalConcept,Tree>;
173 using allowStaticTraversal = Dune::Std::is_detected<StaticTraversalConcept,Tree>;
176 static_assert(allowDynamicTraversal::value || allowStaticTraversal::value);
178 if constexpr(allowDynamicTraversal::value) {
180 for (std::size_t i = 0; i < tree.degree(); ++i) {
181 auto childTreePath = Dune::TypeTree::push_back(
treePath, i);
182 forEachNode(tree.child(i), childTreePath, preFunc, leafFunc, postFunc);
184 }
else if constexpr(allowStaticTraversal::value) {
186 auto indices = std::make_index_sequence<
Tree::degree()>{};
187 Hybrid::forEach(indices, [&](
auto i) {
188 auto childTreePath = Dune::TypeTree::push_back(
treePath, i);
189 forEachNode(tree.child(i), childTreePath, preFunc, leafFunc, postFunc);
216 template<
class Tree, TreePathType::Type pathType=TreePathType::dynamic>
219 return Detail::leafTreePathTuple<std::decay_t<Tree>, pathType>(
hybridTreePath());
237 template<
typename Tree,
typename Visitor>
258 template<
class Tree,
class PreNodeFunc,
class LeafNodeFunc,
class PostNodeFunc>
259 void forEachNode(Tree&& tree, PreNodeFunc&& preNodeFunc, LeafNodeFunc&& leafNodeFunc, PostNodeFunc&& postNodeFunc)
273 template<
class Tree,
class NodeFunc>
288 template<
class Tree,
class LeafFunc>
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:184
constexpr auto treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:199
void forEachNode(Tree &&tree, NodeFunc &&nodeFunc)
Traverse tree and visit each node.
Definition: traversal.hh:274
constexpr auto leafTreePathTuple()
Create tuple of tree paths to leafs.
Definition: traversal.hh:217
void forEachLeafNode(Tree &&tree, LeafFunc &&leafFunc)
Traverse tree and visit each leaf node.
Definition: traversal.hh:289
void applyToTree(Tree &&tree, Visitor &&visitor)
Apply visitor to TypeTree.
Definition: traversal.hh:238