Visitor.hpp 4.19 KB
Newer Older
1
2
3
#pragma once

#include <dune/typetree/visitor.hh>
4
5
#include <amdis/common/Mpl.hpp>
#include <amdis/utility/Traversal.hpp>
6
7
8

namespace AMDiS
{
9
10
  // from dune-typetree merge-request !2
  namespace Impl
11
  {
12
13
14
15
16
17
    struct CallInnerNode
    {
      template <class Node, class /*TreePath*/>
      using Visit = bool_t<Node::isPower && Node::template Child<0>::type::isLeaf>;
    };

18
19
20
21
22
23
    struct CallAnyNode
    {
      template <class /*Node*/, class /*TreePath*/>
      using Visit = std::true_type;
    };

24
25
26
    template <class PreFunc, class LeafFunc, class PostFunc>
    class CallbackVisitor
        : public Dune::TypeTree::TreeVisitor
27
        , public CallAnyNode
28
    {
29
30
31
32
33
34
35
36
37
    public:
      CallbackVisitor(PreFunc& preFunc, LeafFunc& leafFunc, PostFunc& postFunc)
        : preFunc_(preFunc)
        , leafFunc_(leafFunc)
        , postFunc_(postFunc)
      {}

      template <typename Node, typename TreePath>
      void pre(Node&& node, TreePath treePath)
38
      {
39
40
41
        static_assert(std::decay_t<Node>::isPower || std::decay_t<Node>::isComposite, "");
        Dune::Hybrid::ifElse(Visit<std::decay_t<Node>, TreePath>{},
          [&](auto id) { id(preFunc_)(node, treePath); });
42
      }
43

44
45
      template <typename Node, typename TreePath>
      void leaf(Node&& node, TreePath treePath)
46
      {
47
        leafFunc_(node, treePath);
48
49
      }

50
51
      template <typename Node, typename TreePath>
      void post(Node&& node, TreePath treePath)
52
      {
53
54
55
        static_assert(std::decay_t<Node>::isPower || std::decay_t<Node>::isComposite, "");
        Dune::Hybrid::ifElse(Visit<std::decay_t<Node>, TreePath>{},
          [&](auto id) { id(postFunc_)(node, treePath); });
56
57
      }

58
59
60
61
62
    private:
      PreFunc& preFunc_;
      LeafFunc& leafFunc_;
      PostFunc& postFunc_;
    };
63

64
65
    template <class PreFunc, class LeafFunc, class PostFunc>
    auto callbackVisitor(PreFunc& preFunc, LeafFunc& leafFunc, PostFunc& postFunc)
66
    {
67
      return CallbackVisitor<PreFunc, LeafFunc, PostFunc>(preFunc, leafFunc, postFunc);
68
69
    }

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  } // namespace Impl


  /**
    * \brief Traverse tree and visit each node
    *
    * All passed callback functions are called with the
    * node and corresponding treepath as arguments.
    *
    * \param tree The tree to traverse
    * \param preFunc This function is called for each inner node before visiting its children
    * \param leafFunc This function is called for each leaf node
    * \param postFunc This function is called for each inner node after visiting its children
    */
  template <class Tree, class PreFunc, class LeafFunc, class PostFunc>
  void forEachNode(Tree&& tree, PreFunc&& preFunc, LeafFunc&& leafFunc, PostFunc&& postFunc)
  {
87
    traverseTree(tree, Impl::callbackVisitor(preFunc, leafFunc, postFunc));
88
  }
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  /**
    * \brief Traverse tree and visit each node
    *
    * All passed callback functions are called with the
    * node and corresponding treepath as arguments.
    *
    * \param tree The tree to traverse
    * \param innerFunc This function is called for each inner node before visiting its children
    * \param leafFunc This function is called for each leaf node
    */
  template <class Tree, class InnerFunc, class LeafFunc>
  void forEachNode(Tree&& tree, InnerFunc&& innerFunc, LeafFunc&& leafFunc)
  {
    auto nop = [](auto&&... args) {};
    forEachNode(tree, innerFunc, leafFunc, nop);
  }
106

107
108
109
110
111
112
113
114
115
116
117
  /**
    * \brief Traverse tree and visit each node
    *
    * The passed callback function is called with the
    * node and corresponding treepath as arguments.
    *
    * \param tree The tree to traverse
    * \param nodeFunc This function is called for each node
    */
  template <class Tree, class NodeFunc>
  void forEachNode(Tree&& tree, NodeFunc&& nodeFunc)
118
  {
119
    forEachNode(tree, nodeFunc, nodeFunc);
120
121
  }

122
123
124
125
126
127
128
129
130
131
132
  /**
    * \brief Traverse tree and visit each leaf node
    *
    * The passed callback function is called with the
    * node and corresponding treepath as arguments.
    *
    * \param tree The tree to traverse
    * \param leafFunc This function is called for each leaf node
    */
  template <class Tree, class LeafFunc>
  void forEachLeafNode(Tree&& tree, LeafFunc&& leafFunc)
133
  {
134
135
    auto nop = [](auto&&... args) {};
    forEachNode(tree, nop, leafFunc, nop);
136
137
138
  }

} // end namespace AMDiS