dune-typetree  2.4-dev
applytochildrensingletree.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 
4 #ifndef DUNE_TYPETREE_APPLYTOCHILDRENSINGLETREE_HH
5 #define DUNE_TYPETREE_APPLYTOCHILDRENSINGLETREE_HH
6 
7 #include <dune/common/typetraits.hh>
8 
11 #include <dune/typetree/visitor.hh>
12 
13 namespace Dune {
14  namespace TypeTree {
15 
21 #ifndef DOXYGEN // these are all internals and not public API.
22 
23  // forward declaration of main engine struct
24  template<TreePathType::Type tpType, typename tag = StartTag, bool doApply = true>
25  struct ApplyToTree;
26 
27  namespace {
28 
29  // For the CompositeNode, we do need a TMP for iterating over the
30  // children. Note that we use an index that counts down instead of up.
31  // This allows us to specialize the TMP for the last child, where we
32  // do not want to invoke the infix visitor on the CompositeNode.
33 
34  // There are two versions of this TMP, one for iteration with a static TreePath, and one
35  // for iteration with a dynamic TreePath.
36 
37 
38 
39 
40  // ********************************************************************************
41  // Static Version
42  // ********************************************************************************
43 
44  template<std::size_t inverse_k, std::size_t count>
45  struct apply_to_children_fully_static
46  {
47 
48  template<typename N, typename V, typename TreePath>
49  static void apply(N&& n, V&& v, TreePath tp)
50  {
51  // make sure we do not try to work with references to the actual types
52  typedef typename remove_reference<N>::type Node;
53  typedef typename remove_reference<V>::type Visitor;
54 
55  // get child type
56  typedef typename Node::template Child<count-inverse_k>::Type C;
57 
58  // extend TreePath by child index
59  typedef typename TreePathPushBack<TreePath,count-inverse_k>::type ChildTreePath;
60 
61  // is the visitor interested in this child?
62  const bool visit = Visitor::template VisitChild<Node,C,ChildTreePath>::value;
63 
64  // beforeChild() gets called regardless of the value of visit
65  v.beforeChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
66 
67  // traverse to child
68  ApplyToTree<Visitor::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),
69  std::forward<V>(v),
70  ChildTreePath());
71 
72  // afterChild() gets called regardless of the value of visit
73  v.afterChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp,integral_constant<std::size_t,count-inverse_k>());
74 
75  // we are not at the last child (that is specialized), so call infix visitor callback
76  v.in(std::forward<N>(n),tp);
77 
78  // continue with next child
79  apply_to_children_fully_static<inverse_k-1,count>::apply(std::forward<N>(n),
80  std::forward<V>(v),
81  tp);
82  }
83 
84  };
85 
86  // Specialization for last child. This specialization stops the recursion and
87  // does not call the infix visitor on the CompositeNode.
88  template<std::size_t count>
89  struct apply_to_children_fully_static<1,count>
90  {
91 
92  template<typename N, typename V, typename TreePath>
93  static void apply(N&& n, V&& v, TreePath tp)
94  {
95  typedef typename remove_reference<N>::type Node;
96  typedef typename remove_reference<V>::type Visitor;
97  typedef typename Node::template Child<count-1>::Type C;
98  typedef typename TreePathPushBack<TreePath,count-1>::type ChildTreePath;
99  const bool visit = Visitor::template VisitChild<Node,C,ChildTreePath>::value;
100  v.beforeChild(std::forward<N>(n),n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
101  ApplyToTree<Visitor::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),
102  std::forward<V>(v),
103  ChildTreePath());
104  v.afterChild(std::forward<N>(n),n.template child<count-1>(),tp,integral_constant<std::size_t,count-1>());
105  }
106 
107  };
108 
109  // Specialization for CompositeNode without any children.
110  template<>
111  struct apply_to_children_fully_static<0,0>
112  {
113 
114  template<typename N, typename V, typename TreePath>
115  static void apply(N&& n, V&& v, TreePath tp) {}
116 
117  };
118 
119 
120 
121 
122  // ********************************************************************************
123  // Dynamic Version
124  // ********************************************************************************
125 
126  template<std::size_t inverse_k, std::size_t count>
127  struct apply_to_children_dynamic
128  {
129 
130  template<typename N, typename V, typename TreePath>
131  static void apply(N&& n, V&& v, TreePath tp)
132  {
133  typedef typename remove_reference<N>::type Node;
134  typedef typename remove_reference<V>::type Visitor;
135  typedef typename Node::template Child<count-inverse_k>::Type C;
136  const bool visit = Visitor::template VisitChild<Node,C,typename TreePath::ViewType>::value;
137  v.beforeChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
138  tp.push_back(count-inverse_k);
139  ApplyToTree<Visitor::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-inverse_k>(),
140  std::forward<V>(v),
141  tp);
142  tp.pop_back();
143  v.afterChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp.view(),count-inverse_k);
144  v.in(std::forward<N>(n),tp.view());
145  apply_to_children_dynamic<inverse_k-1,count>::apply(std::forward<N>(n),
146  std::forward<V>(v),
147  tp);
148  }
149 
150  };
151 
152  // Specialization for last child. This specialization stops the recursion and
153  // does not call the infix visitor on the CompositeNode.
154  template<std::size_t count>
155  struct apply_to_children_dynamic<1,count>
156  {
157 
158  template<typename N, typename V, typename TreePath>
159  static void apply(N&& n, V&& v, TreePath tp)
160  {
161  typedef typename remove_reference<N>::type Node;
162  typedef typename remove_reference<V>::type Visitor;
163  typedef typename Node::template Child<count-1>::Type C;
164  const bool visit = Visitor::template VisitChild<Node,C,typename TreePath::ViewType>::value;
165  v.beforeChild(std::forward<N>(n),n.template child<count-1>(),tp.view(),count-1);
166  tp.push_back(count-1);
167  ApplyToTree<Visitor::treePathType,typename C::NodeTag,visit>::apply(n.template child<count-1>(),
168  std::forward<V>(v),
169  tp);
170  tp.pop_back();
171  v.afterChild(std::forward<N>(n),n.template child<count-1>(),tp.view(),count-1);
172  }
173 
174  };
175 
176  // Specialization for CompositeNode without any children.
177  template<>
178  struct apply_to_children_dynamic<0,0>
179  {
180 
181  template<typename N, typename V, typename TreePath>
182  static void apply(N&& n, V&& v, TreePath tp) {}
183 
184  };
185 
186 
187  // helper struct for automatically picking the right traversal
188  // algorithm variant
189  template<TreePathType::Type treePathType, std::size_t CHILDREN>
190  struct apply_to_children;
191 
192  template<std::size_t CHILDREN>
193  struct apply_to_children<TreePathType::fullyStatic,CHILDREN>
194  : public apply_to_children_fully_static<CHILDREN,CHILDREN>
195  {};
196 
197  template<std::size_t CHILDREN>
198  struct apply_to_children<TreePathType::dynamic,CHILDREN>
199  : public apply_to_children_dynamic<CHILDREN,CHILDREN>
200  {};
201 
202 
203  } // anonymous namespace
204 
205 
206 
207  // Base class for composite node traversal
208 
209  // The traversal algorithm is identical for CompositeNode
210  // and PowerNode int the case of static traversal,
211  // so the implementation can be bundled
212  // in a single base class.
213  struct ApplyToGenericCompositeNode
214  {
215 
216  template<typename N, typename V, typename TreePath>
217  static void apply(N&& n, V&& v, TreePath tp)
218  {
219  v.pre(std::forward<N>(n),tp);
220  typedef typename remove_reference<N>::type Node;
221  typedef typename remove_reference<V>::type Visitor;
222  apply_to_children<Visitor::treePathType,Node::CHILDREN>::apply(std::forward<N>(n),
223  std::forward<V>(v),
224  tp);
225  v.post(std::forward<N>(n),tp);
226  }
227 
228  };
229 
230 #endif // DOXYGEN
231 
233 
234  } // namespace TypeTree
235 } //namespace Dune
236 
237 #endif // DUNE_TYPETREE_APPLYTOCHILDRENSINGLETREE_HH
Definition: accumulate_static.hh:12
Type
Definition: treepath.hh:25
Definition: treepath.hh:25