dune-typetree  2.8.0
utility.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_UTILITY_HH
5 #define DUNE_TYPETREE_UTILITY_HH
6 
7 #include <memory>
8 #include <tuple>
9 #include <type_traits>
10 #include <utility>
11 #include <algorithm>
12 
13 #include <dune/common/shared_ptr.hh>
14 #include <dune/common/indices.hh>
15 #include <dune/common/hybridutilities.hh>
18 
19 namespace Dune {
20  namespace TypeTree {
21 
26 #ifndef DOXYGEN
27 
28  template<typename T>
29  std::shared_ptr<T> convert_arg(const T& t)
30  {
31  return std::make_shared<T>(t);
32  }
33 
34  template<typename T>
35  std::shared_ptr<T> convert_arg(T& t)
36  {
37  return stackobject_to_shared_ptr(t);
38  }
39 
40  template<typename BaseType, typename T>
41  T& assertGridViewType(T& t)
42  {
43  static_assert((std::is_same<typename BaseType::Traits::GridViewType,
44  typename T::Traits::GridViewType>::value),
45  "GridViewType must be equal in all components of composite type");
46  return t;
47  }
48 
49  // only bind to real rvalues
50  template<typename T>
51  typename std::enable_if<!std::is_lvalue_reference<T>::value,std::shared_ptr<T> >::type convert_arg(T&& t)
52  {
53  return std::make_shared<T>(std::forward<T>(t));
54  }
55 
56 
57  namespace Experimental {
58 
67  template<class BinaryOp, class Arg>
68  constexpr decltype(auto)
69  left_fold(BinaryOp&& binary_op, Arg&& arg)
70  {
71  return std::forward<Arg>(arg);
72  }
73 
95  template<class BinaryOp, class Init, class Arg0, class... Args>
96  constexpr decltype(auto)
97  left_fold(BinaryOp&& binary_op, Init&& init, Arg0&& arg_0, Args&&... args)
98  {
99  return left_fold(
100  std::forward<BinaryOp>(binary_op),
101  binary_op(std::forward<Init>(init), std::forward<Arg0>(arg_0)),
102  std::forward<Args>(args)...);
103  }
104 
105 
106  namespace Hybrid {
107  using namespace Dune::Hybrid;
108 
109  namespace Detail {
110  template<class Op, class... Args>
111  constexpr auto applyOperator(Op&& op, Args&&... args)
112  {
113  using T = std::common_type_t<Args...>;
114  return op(static_cast<T>(args)...);
115  }
116 
117  template<class Op, class T, T... Args>
118  constexpr auto applyOperator(Op, std::integral_constant<T,Args>...)
119  {
120  static_assert(std::is_default_constructible_v<Op>,
121  "Operator in integral expressions shall be default constructible");
122  constexpr auto result = Op{}(T{Args}...);
123  return std::integral_constant<std::decay_t<decltype(result)>,result>{};
124  }
125 
126  // FIXME: use lambda when we adpot c++20
127  struct Max {
128  template<class... Args>
129  constexpr auto operator()(Args&&... args) const
130  {
131  using T = std::common_type_t<Args...>;
132  return std::max({static_cast<T>(args)...});
133  }
134  };
135  }
136 
137  static constexpr auto max = [](const auto& a, const auto& b)
138  {
139  return Detail::applyOperator(Detail::Max{}, a, b);
140  };
141 
142  static constexpr auto plus = [](const auto& a, const auto& b)
143  {
144  return Detail::applyOperator(std::plus<>{}, a, b);
145  };
146 
147  static constexpr auto minus = [](const auto& a, const auto& b)
148  {
149  return Detail::applyOperator(std::minus<>{}, a, b);
150  };
151  } // namespace Hybrid
152 
153  } // namespace Experimental
154 
155 
156 #endif // DOXYGEN
157 
159 
166  template<typename Tree, typename Tag = StartTag>
167  struct TreeInfo
168  {
169 
170  private:
171  // Start the tree traversal
173 
174  public:
175 
177  static const std::size_t depth = NodeInfo::depth;
178 
180  static const std::size_t nodeCount = NodeInfo::nodeCount;
181 
183  static const std::size_t leafCount = NodeInfo::leafCount;
184 
185  };
186 
187 
188 #ifndef DOXYGEN
189 
190  // ********************************************************************************
191  // TreeInfo specializations for the different node types
192  // ********************************************************************************
193 
194 
195  // leaf node
196  template<typename Node>
197  struct TreeInfo<Node,LeafNodeTag>
198  {
199 
200  static const std::size_t depth = 1;
201 
202  static const std::size_t nodeCount = 1;
203 
204  static const std::size_t leafCount = 1;
205 
206  };
207 
208 
209  // power node - exploit the fact that all children are identical
210  template<typename Node>
211  struct TreeInfo<Node,PowerNodeTag>
212  {
213 
214  typedef TreeInfo<typename Node::ChildType,NodeTag<typename Node::ChildType>> ChildInfo;
215 
216  static const std::size_t depth = 1 + ChildInfo::depth;
217 
218  static const std::size_t nodeCount = 1 + StaticDegree<Node>::value * ChildInfo::nodeCount;
219 
220  static const std::size_t leafCount = StaticDegree<Node>::value * ChildInfo::leafCount;
221 
222  };
223 
224 
225  namespace {
226 
227  // TMP for iterating over the children of a composite node
228  // identical for both composite node implementations
229  template<typename Node, std::size_t k, std::size_t n>
230  struct generic_compositenode_children_info
231  {
232 
233  typedef generic_compositenode_children_info<Node,k+1,n> NextChild;
234 
235  // extract child info
236  typedef typename Node::template Child<k>::Type Child;
237  typedef NodeTag<Child> ChildTag;
238  typedef TreeInfo<Child,ChildTag> ChildInfo;
239 
240  // combine information of current child with info about following children
241  static const std::size_t maxDepth = ChildInfo::depth > NextChild::maxDepth ? ChildInfo::depth : NextChild::maxDepth;
242 
243  static const std::size_t nodeCount = ChildInfo::nodeCount + NextChild::nodeCount;
244 
245  static const std::size_t leafCount = ChildInfo::leafCount + NextChild::leafCount;
246 
247  };
248 
249  // End of recursion
250  template<typename Node, std::size_t n>
251  struct generic_compositenode_children_info<Node,n,n>
252  {
253  static const std::size_t maxDepth = 0;
254 
255  static const std::size_t nodeCount = 0;
256 
257  static const std::size_t leafCount = 0;
258  };
259 
260  } // anonymous namespace
261 
262 
263  // Struct for building information about composite node
264  template<typename Node>
265  struct GenericCompositeNodeInfo
266  {
267 
268  typedef generic_compositenode_children_info<Node,0,StaticDegree<Node>::value> Children;
269 
270  static const std::size_t depth = 1 + Children::maxDepth;
271 
272  static const std::size_t nodeCount = 1 + Children::nodeCount;
273 
274  static const std::size_t leafCount = Children::leafCount;
275 
276  };
277 
278 
279  // CompositeNode: delegate to GenericCompositeNodeInfo
280  template<typename Node>
281  struct TreeInfo<Node,CompositeNodeTag>
282  : public GenericCompositeNodeInfo<Node>
283  {};
284 
285 
286 #endif // DOXYGEN
287 
288 
289  using Dune::index_constant;
290  namespace Indices = Dune::Indices;
291 
293  template<typename... Args>
294  void discard(Args&&... args)
295  {}
296 
298  namespace apply_to_tuple_policy {
299 
301  struct no_pass_index {};
302 
304  struct pass_index {};
305 
308 
309  }
310 
311  namespace {
312 
313  // version that does not pass index
314  template<typename T, typename F, std::size_t... i>
315  void _apply_to_tuple(T&& t, F&& f, std::index_sequence<i...>,apply_to_tuple_policy::no_pass_index)
316  {
317  discard((f(std::get<i>(std::forward<T>(t))),0)...);
318  }
319 
320  // version that passes index
321  template<typename T, typename F, std::size_t... i>
322  void _apply_to_tuple(T&& t, F&& f, std::index_sequence<i...>,apply_to_tuple_policy::pass_index)
323  {
324  discard((f(index_constant<i>{},std::get<i>(std::forward<T>(t))),0)...);
325  }
326 
327  }
328 
330  /*
331  * This function applies the functor f to each element of the std::tuple t.
332  * It works for arbitrary combinations of const- and non const lvalues and rvalues.
333  * The function accepts an optional policy argument that can currently be used to make
334  * it pass the index of the current tuple argument to the functor as a compile time constant
335  * in addition to the tuple element itself.
336  */
337  template<typename T, typename F, typename Policy>
339  {
340  const std::size_t size = std::tuple_size<typename std::decay<T>::type>::value;
341  _apply_to_tuple(
342  std::forward<T>(t),
343  std::forward<F>(f),
344  std::make_index_sequence<size>{},
345  Policy()
346  );
347  }
348 
350 
351  } // namespace TypeTree
352 } //namespace Dune
353 
354 #endif // DUNE_TYPETREE_UTILITY_HH
static const result_type result
Definition: accumulate_static.hh:110
void apply_to_tuple(T &&t, F &&f, Policy=apply_to_tuple_policy::default_policy())
Apply a functor to each element of a std::tuple.
Definition: utility.hh:338
void discard(Args &&... args)
No-op function to make calling a function on a variadic template argument pack legal C++.
Definition: utility.hh:294
typename impl::_Child< Node, indices... >::type Child
Template alias for the type of a child node given by a list of child indices.
Definition: childextraction.hh:223
Definition: accumulate_static.hh:13
Type
Definition: treepath.hh:30
no_pass_index default_policy
Default policy.
Definition: utility.hh:307
auto leafCount(const Tree &tree)
The number of leaf nodes in the Tree.
Definition: visitor.hh:530
auto nodeCount(const Tree &tree)
The total number of nodes in the Tree.
Definition: visitor.hh:522
auto depth(const Tree &tree)
The depth of the TypeTree.
Definition: visitor.hh:506
Tag designating a leaf node.
Definition: nodetags.hh:16
Struct for obtaining some basic structural information about a TypeTree.
Definition: utility.hh:168
Do not pass the index of the current tuple to the functor.
Definition: utility.hh:301
Pass the index of the current tuple to the functor as its first argument in a std::integral_constant.
Definition: utility.hh:304