dune-common  2.11
traversal.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 // SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
5 
6 #ifndef DUNE_COMMON_TYPETREE_TRAVERSAL_HH
7 #define DUNE_COMMON_TYPETREE_TRAVERSAL_HH
8 
9 #include <utility>
10 
12 #include <dune/common/indices.hh>
14 
18 
19 namespace Dune::TypeTree {
20 
21  namespace Impl {
22 
23  template<class Callable, class Arg0, class Arg1>
24  constexpr void invokeWithTwoOrOneArg(Callable&& callable, Arg0&& arg0, Arg1&& arg1) {
25  static_assert(std::invocable<Callable&&, Arg0&&, Arg1&&> || std::invocable<Callable&&, Arg0&&>);
26  if constexpr (std::invocable<Callable&&, Arg0&&, Arg1&&>)
27  callable(arg0, arg1);
28  else if constexpr (std::invocable<Callable&&, Arg0&&>)
29  callable(arg0);
30  };
31 
32  } // namespace Impl
33 
39 #ifndef DOXYGEN
40  struct NoOp
42  {
43  template<class... T>
44  constexpr void operator()(T&&...) const { /* do nothing */ }
45  };
46 #endif
47 
66  template<Concept::InnerTreeNode Tree, class Callable>
67  constexpr void forEachChild(Tree&& container, Callable&& at_value)
68  {
69  if constexpr (Concept::UniformInnerTreeNode<Tree>)
70  for (std::size_t i = 0; i != container.degree(); ++i)
71  Impl::invokeWithTwoOrOneArg(at_value, std::forward<Tree>(container).child(i), i);
72  else
74  [&](auto... i) { (Impl::invokeWithTwoOrOneArg(at_value, std::forward<Tree>(container).child(i), i), ...); },
75  std::make_index_sequence<std::remove_cvref_t<Tree>::degree()>{});
76  }
77 
78  namespace Impl {
79 
80  /* Traverse tree and visit each node. The signature is the same
81  * as for the public forEachNode function in Dune::Typtree,
82  * despite the additionally passed treePath argument. The path
83  * passed here is associated to the tree and the relative
84  * paths of the children (wrt. to tree) are appended to this.
85  * Hence the behavior of the public function is resembled
86  * by passing an empty treePath.
87  */
88  template<Concept::TreeNode Tree, class TreePath, class PreFunc, class LeafFunc, class PostFunc>
89  void forEachNode(Tree&& tree, TreePath treePath, PreFunc&& preFunc, LeafFunc&& leafFunc, PostFunc&& postFunc)
90  {
91  if constexpr(Concept::LeafTreeNode<std::decay_t<Tree>>) {
92  Impl::invokeWithTwoOrOneArg(leafFunc, tree, treePath);
93  } else {
94  Impl::invokeWithTwoOrOneArg(preFunc, tree, treePath);
96  tree,
97  [&]<class Child>(Child&& child, auto i) {
99  std::forward<Child>(child),
100  push_back(treePath, i),
101  preFunc,
102  leafFunc,
103  postFunc
104  );
105  });
106  Impl::invokeWithTwoOrOneArg(postFunc, tree, treePath);
107  }
108  }
109 
110  } // namespace Impl
111 
112 
113  // ********************************************************************************
114  // Public Interface
115  // ********************************************************************************
116 
132  template<class Tree, class PreNodeFunc, class LeafNodeFunc, class PostNodeFunc>
133  void forEachNode(Tree&& tree, PreNodeFunc&& preNodeFunc, LeafNodeFunc&& leafNodeFunc, PostNodeFunc&& postNodeFunc)
134  {
135  Impl::forEachNode(tree, treePath(), preNodeFunc, leafNodeFunc, postNodeFunc);
136  }
137 
147  template<Concept::TreeNode Tree, class NodeFunc>
148  void forEachNode(Tree&& tree, NodeFunc&& nodeFunc)
149  {
150  forEachNode(tree, nodeFunc, nodeFunc, NoOp{});
151  }
152 
162  template<Concept::TreeNode Tree, class LeafFunc>
163  void forEachLeafNode(Tree&& tree, LeafFunc&& leafFunc)
164  {
165  forEachNode(tree, NoOp{}, leafFunc, NoOp{});
166  }
167 
169 
170 } //namespace Dune::TypeTree
171 
172 #endif // DUNE_COMMON_TYPETREE_TRAVERSAL_HH
typename Impl::ChildTraits< Node, indices... >::type Child
Template alias for the type of a child node given by a list of child indices.
Definition: childaccess.hh:129
decltype(auto) constexpr unpackIntegerSequence(F &&f, [[maybe_unused]] std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition: indices.hh:124
constexpr void forEachChild(Tree &&container, Callable &&at_value)
Traverse each child of a tree and apply a callable function.
Definition: traversal.hh:67
void forEachNode(Tree &&tree, NodeFunc &&nodeFunc)
Traverse tree and visit each node.
Definition: traversal.hh:148
I i
Definition: hybridmultiindex.hh:328
Definition: childaccess.hh:23
decltype(auto) child(Node &&node, TreePath< Indices... > treePath)
Extracts the child of a node given by a TreePath object.
Definition: childaccess.hh:55
Dune::HybridMultiIndex< T... > TreePath
A type for representing tree paths that supports both compile time and run time indices.
Definition: treepath.hh:43
void forEachNode(Tree &&tree, PreNodeFunc &&preNodeFunc, LeafNodeFunc &&leafNodeFunc, PostNodeFunc &&postNodeFunc)
Traverse tree and visit each node.
Definition: traversal.hh:133
concept LeafTreeNode
Model of a leaf tree node of a typetree.
Definition: nodeconcepts.hh:63
constexpr HybridMultiIndex< T..., std::size_t > push_back(const HybridMultiIndex< T... > &tp, std::size_t i)
Appends a run time index to a HybridMultiIndex.
Definition: hybridmultiindex.hh:249
void forEachLeafNode(Tree &&tree, LeafFunc &&leafFunc)
Traverse tree and visit each leaf node.
Definition: traversal.hh:163