dune-typetree  2.9
treepath.hh
Go to the documentation of this file.
1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=8 sw=2 sts=2:
3 
4 #ifndef DUNE_TYPETREE_TREEPATH_HH
5 #define DUNE_TYPETREE_TREEPATH_HH
6 
7 #include <cstddef>
8 #include <iostream>
9 
10 #include <dune/common/documentation.hh>
11 #include <dune/common/typetraits.hh>
12 #include <dune/common/indices.hh>
13 #include <dune/common/hybridutilities.hh>
14 
16 #include <dune/typetree/utility.hh>
17 
18 
19 namespace Dune {
20  namespace TypeTree {
21 
22  template<typename... T>
23  class HybridTreePath;
24 
28 
29  namespace TreePathType {
31  }
32 
33  template<typename>
34  struct TreePathSize;
35 
36  template<typename,std::size_t>
38 
39  template<typename,std::size_t>
41 
42  template<typename>
43  struct TreePathBack;
44 
45  template<typename>
46  struct TreePathFront;
47 
48  template<typename, std::size_t...>
50 
51  template<typename>
53 
54  template<typename, typename>
56 
57  template<std::size_t... i>
58  void print_tree_path(std::ostream& os)
59  {}
60 
61  template<std::size_t k, std::size_t... i>
62  void print_tree_path(std::ostream& os)
63  {
64  os << k << " ";
65  print_tree_path<i...>(os);
66  }
67 
69 
77  template<typename... T>
79  {
80 
81  public:
82 
84  using index_sequence = std::index_sequence_for<T...>;
85 
87  constexpr HybridTreePath()
88  {}
89 
90  constexpr HybridTreePath(const HybridTreePath& tp) = default;
91  constexpr HybridTreePath(HybridTreePath&& tp) = default;
92 
93  constexpr HybridTreePath& operator=(const HybridTreePath& tp) = default;
94  constexpr HybridTreePath& operator=(HybridTreePath&& tp) = default;
95 
97  explicit constexpr HybridTreePath(std::tuple<T...> t)
98  : _data(t)
99  {}
100 
102  template<typename... U, typename std::enable_if<(sizeof...(T) > 0 && sizeof...(U) == sizeof...(T)),bool>::type = true>
103  explicit constexpr HybridTreePath(U... t)
104  : _data(t...)
105  {}
106 
108  constexpr static index_sequence enumerate()
109  {
110  return {};
111  }
112 
114  constexpr static std::size_t size()
115  {
116  return sizeof...(T);
117  }
118 
120  template<std::size_t i>
121  constexpr auto operator[](Dune::index_constant<i>) const
122  {
123  return std::get<i>(_data);
124  }
125 
127  constexpr std::size_t operator[](std::size_t pos) const
128  {
129  std::size_t entry = 0;
130  Dune::Hybrid::forEach(enumerate(), [&] (auto i) {
131  if (i==pos)
132  entry = this->element(i);
133  });
134  return entry;
135  }
136 
138  template<std::size_t i>
139  constexpr auto element(Dune::index_constant<i> pos = {}) const
140  {
141  return std::get<i>(_data);
142  }
143 
145  constexpr std::size_t element(std::size_t pos) const
146  {
147  std::size_t entry = 0;
148  Dune::Hybrid::forEach(enumerate(), [&] (auto i) {
149  if (i==pos)
150  entry = this->element(i);
151  });
152  return entry;
153  }
154 
156  auto back() const
157  {
158  return std::get<sizeof...(T)-1>(_data);
159  }
160 
161 #ifndef DOXYGEN
162 
163  // I can't be bothered to make all the external accessors friends of HybridTreePath,
164  // so we'll only hide the data tuple from the user in Doxygen.
165 
166  using Data = std::tuple<T...>;
167  Data _data;
168 
169 #endif // DOXYGEN
170 
171  };
172 
173 
175 
179  template<typename... T>
180  constexpr HybridTreePath<T...> hybridTreePath(const T&... t)
181  {
182  return HybridTreePath<T...>(t...);
183  }
184 
186 
190  template<typename... T>
191  constexpr HybridTreePath<T...> treePath(const T&... t)
192  {
193  return HybridTreePath<T...>(t...);
194  }
195 
196 
198  template<typename... T>
199  constexpr std::size_t treePathSize(const HybridTreePath<T...>&)
200  {
201  return sizeof...(T);
202  }
203 
205 
221  template<std::size_t i, typename... T>
222  constexpr auto treePathEntry(const HybridTreePath<T...>& tp, index_constant<i> = {})
223  -> typename std::decay<decltype(std::get<i>(tp._data))>::type
224  {
225  return std::get<i>(tp._data);
226  }
227 
229 
244  template<std::size_t i,typename... T>
245  constexpr std::size_t treePathIndex(const HybridTreePath<T...>& tp, index_constant<i> = {})
246  {
247  return std::get<i>(tp._data);
248  }
249 
251 
256  template<typename... T, typename std::enable_if<(sizeof...(T) > 0),bool>::type = true>
257  constexpr auto back(const HybridTreePath<T...>& tp)
258  -> decltype(treePathEntry<sizeof...(T)-1>(tp))
259  {
260  return treePathEntry<sizeof...(T)-1>(tp);
261  }
262 
264 
269  template<typename... T>
270  constexpr auto front(const HybridTreePath<T...>& tp)
271  -> decltype(treePathEntry<0>(tp))
272  {
273  return treePathEntry<0>(tp);
274  }
275 
277 
280  template<typename... T>
281  constexpr HybridTreePath<T...,std::size_t> push_back(const HybridTreePath<T...>& tp, std::size_t i)
282  {
283  return HybridTreePath<T...,std::size_t>(std::tuple_cat(tp._data,std::make_tuple(i)));
284  }
285 
287 
301  template<std::size_t i, typename... T>
302  constexpr HybridTreePath<T...,index_constant<i>> push_back(const HybridTreePath<T...>& tp, index_constant<i> i_ = {})
303  {
304  return HybridTreePath<T...,index_constant<i> >(std::tuple_cat(tp._data,std::make_tuple(i_)));
305  }
306 
308 
311  template<typename... T>
312  constexpr HybridTreePath<std::size_t,T...> push_front(const HybridTreePath<T...>& tp, std::size_t element)
313  {
314  return HybridTreePath<std::size_t,T...>(std::tuple_cat(std::make_tuple(element),tp._data));
315  }
316 
318 
332  template<std::size_t i, typename... T>
333  constexpr HybridTreePath<index_constant<i>,T...> push_front(const HybridTreePath<T...>& tp, index_constant<i> _i = {})
334  {
335  return HybridTreePath<index_constant<i>,T...>(std::tuple_cat(std::make_tuple(_i),tp._data));
336  }
337 
339 
342  template <class... T>
343  constexpr auto pop_front(const HybridTreePath<T...>& tp)
344  {
345  static_assert(sizeof...(T) != 0, "HybridTreePath must not be empty");
346  return unpackIntegerSequence([&](auto... i){
347  return HybridTreePath{std::make_tuple(std::get<i+1>(tp._data)...)};
348  }, std::make_index_sequence<(sizeof...(T) - 1)>{});
349  }
350 
352 
355  template <class... T>
356  constexpr auto pop_back(const HybridTreePath<T...>& tp)
357  {
358  static_assert(sizeof...(T) != 0, "HybridTreePath must not be empty");
359  return unpackIntegerSequence([&](auto... i){
360  return HybridTreePath{std::make_tuple(std::get<i>(tp._data)...)};
361  }, std::make_index_sequence<(sizeof...(T) - 1)>{});
362  }
363 
365 
373  template <class... S, class... T>
374  constexpr bool operator==(
375  const HybridTreePath<S...>& lhs,
376  const HybridTreePath<T...>& rhs)
377  {
378  if constexpr (sizeof...(S) == sizeof...(T)) {
379  if constexpr ((Dune::IsInteroperable<S,T>::value &&...)) {
380  return unpackIntegerSequence([&](auto... i){
381  return ((std::get<i>(lhs._data) == std::get<i>(rhs._data)) &&...);
382  }, std::make_index_sequence<(sizeof...(S))>{});
383  } else {
384  return false;
385  }
386  } else {
387  return false;
388  }
389  }
390 
392 
397  template <class S, S... lhs, class T, T... rhs>
398  constexpr auto operator==(
399  const HybridTreePath<std::integral_constant<S,lhs>...>&,
400  const HybridTreePath<std::integral_constant<T,rhs>...>&)
401  {
402  return std::bool_constant<hybridTreePath(lhs...) == hybridTreePath(rhs...)>{};
403  }
404 
405 
407  template <class... S, class... T>
408  constexpr auto operator!=(
409  const HybridTreePath<S...>& lhs,
410  const HybridTreePath<T...>& rhs)
411  {
412  return !(lhs == rhs);
413  }
414 
416  template <class S, S... lhs, class T, T... rhs>
417  constexpr auto operator!=(
418  const HybridTreePath<std::integral_constant<S,lhs>...>&,
419  const HybridTreePath<std::integral_constant<T,rhs>...>&)
420  {
421  return std::bool_constant<hybridTreePath(lhs...) != hybridTreePath(rhs...)>{};
422  }
423 
424  template<std::size_t... i>
425  struct TreePathSize<HybridTreePath<index_constant<i>...> >
426  : public index_constant<sizeof...(i)>
427  {};
428 
429 
430  template<std::size_t k, std::size_t... i>
431  struct TreePathPushBack<HybridTreePath<index_constant<i>...>,k>
432  {
433  typedef HybridTreePath<index_constant<i>...,index_constant<k>> type;
434  };
435 
436  template<std::size_t k, std::size_t... i>
437  struct TreePathPushFront<HybridTreePath<index_constant<i>...>,k>
438  {
439  typedef HybridTreePath<index_constant<k>,index_constant<i>...> type;
440  };
441 
442  template<std::size_t k>
443  struct TreePathBack<HybridTreePath<index_constant<k>>>
444  : public index_constant<k>
445  {};
446 
447  template<std::size_t j, std::size_t k, std::size_t... l>
448  struct TreePathBack<HybridTreePath<index_constant<j>,index_constant<k>,index_constant<l>...>>
449  : public TreePathBack<HybridTreePath<index_constant<k>,index_constant<l>...>>
450  {};
451 
452  template<std::size_t k, std::size_t... i>
453  struct TreePathFront<HybridTreePath<index_constant<k>,index_constant<i>...>>
454  : public index_constant<k>
455  {};
456 
457  template<std::size_t k, std::size_t... i>
458  struct TreePathPopBack<HybridTreePath<index_constant<k>>,i...>
459  {
461  };
462 
463  template<std::size_t j,
464  std::size_t k,
465  std::size_t... l,
466  std::size_t... i>
467  struct TreePathPopBack<HybridTreePath<index_constant<j>,index_constant<k>,index_constant<l>...>,i...>
468  : public TreePathPopBack<HybridTreePath<index_constant<k>,index_constant<l>...>,i...,j>
469  {};
470 
471  template<std::size_t k, std::size_t... i>
472  struct TreePathPopFront<HybridTreePath<index_constant<k>,index_constant<i>...> >
473  {
475  };
476 
477  template<std::size_t... i, std::size_t... k>
478  struct TreePathConcat<HybridTreePath<index_constant<i>...>,HybridTreePath<index_constant<k>...> >
479  {
480  typedef HybridTreePath<index_constant<i>...,index_constant<k>...> type;
481  };
482 
483 #ifndef DOXYGEN
484 
485  namespace impl {
486 
487  // end of recursion
488  template<std::size_t i, typename... T>
489  typename std::enable_if<
490  (i == sizeof...(T))
491  >::type
492  print_hybrid_tree_path(std::ostream& os, const HybridTreePath<T...>& tp, index_constant<i> _i)
493  {}
494 
495  // print current entry and recurse
496  template<std::size_t i, typename... T>
497  typename std::enable_if<
498  (i < sizeof...(T))
499  >::type
500  print_hybrid_tree_path(std::ostream& os, const HybridTreePath<T...>& tp, index_constant<i> _i)
501  {
502  os << treePathIndex(tp,_i) << " ";
503  print_hybrid_tree_path(os,tp,index_constant<i+1>{});
504  }
505 
506  } // namespace impl
507 
508 #endif // DOXYGEN
509 
511  template<typename... T>
512  std::ostream& operator<<(std::ostream& os, const HybridTreePath<T...>& tp)
513  {
514  os << "HybridTreePath< ";
515  impl::print_hybrid_tree_path(os, tp, index_constant<0>{});
516  os << ">";
517  return os;
518  }
519 
520  template<std::size_t... i>
521  using TreePath [[deprecated("use StaticTreePath, this type will be removed after DUNE 2.7")]] = HybridTreePath<Dune::index_constant<i>...>;
522 
523  template<std::size_t... i>
525 
527 
528  } // namespace TypeTree
529 } //namespace Dune
530 
531 #endif // DUNE_TYPETREE_TREEPATH_HH
constexpr auto pop_front(const HybridTreePath< T... > &tp)
Removes first index on a HybridTreePath.
Definition: treepath.hh:343
constexpr auto back(const HybridTreePath< T... > &tp) -> decltype(treePathEntry< sizeof...(T) -1 >(tp))
Returns a copy of the last element of the HybridTreePath.
Definition: treepath.hh:257
constexpr std::size_t treePathSize(const HybridTreePath< T... > &)
Returns the size (number of components) of the given HybridTreePath.
Definition: treepath.hh:199
constexpr auto front(const HybridTreePath< T... > &tp) -> decltype(treePathEntry< 0 >(tp))
Returns a copy of the first element of the HybridTreePath.
Definition: treepath.hh:270
std::ostream & operator<<(std::ostream &os, const HybridTreePath< T... > &tp)
Dumps a HybridTreePath to a stream.
Definition: treepath.hh:512
constexpr auto treePathEntry(const HybridTreePath< T... > &tp, index_constant< i >={}) -> typename std::decay< decltype(std::get< i >(tp._data))>::type
Returns a copy of the i-th element of the HybridTreePath.
Definition: treepath.hh:222
constexpr HybridTreePath< T... > treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:191
constexpr auto operator!=(const HybridTreePath< S... > &lhs, const HybridTreePath< T... > &rhs)
Compare two HybridTreePaths for unequality.
Definition: treepath.hh:408
constexpr std::size_t treePathIndex(const HybridTreePath< T... > &tp, index_constant< i >={})
Returns the index value of the i-th element of the HybridTreePath.
Definition: treepath.hh:245
constexpr HybridTreePath< T... > hybridTreePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:180
constexpr auto pop_back(const HybridTreePath< T... > &tp)
Removes last index on a HybridTreePath.
Definition: treepath.hh:356
constexpr HybridTreePath< std::size_t, T... > push_front(const HybridTreePath< T... > &tp, std::size_t element)
Prepends a run time index to a HybridTreePath.
Definition: treepath.hh:312
constexpr HybridTreePath< T..., std::size_t > push_back(const HybridTreePath< T... > &tp, std::size_t i)
Appends a run time index to a HybridTreePath.
Definition: treepath.hh:281
constexpr bool operator==(const HybridTreePath< S... > &lhs, const HybridTreePath< T... > &rhs)
Compare two HybridTreePaths for value equality.
Definition: treepath.hh:374
void print_tree_path(std::ostream &os)
Definition: treepath.hh:58
Definition: accumulate_static.hh:13
Type
Definition: treepath.hh:30
@ fullyStatic
Definition: treepath.hh:30
@ dynamic
Definition: treepath.hh:30
A hybrid version of TreePath that supports both compile time and run time indices.
Definition: treepath.hh:79
constexpr HybridTreePath(HybridTreePath &&tp)=default
constexpr std::size_t element(std::size_t pos) const
Get the index value at position pos.
Definition: treepath.hh:145
constexpr HybridTreePath & operator=(HybridTreePath &&tp)=default
constexpr HybridTreePath(std::tuple< T... > t)
Constructor from a std::tuple
Definition: treepath.hh:97
constexpr static std::size_t size()
Get the size (length) of this path.
Definition: treepath.hh:114
constexpr HybridTreePath(U... t)
Constructor from arguments.
Definition: treepath.hh:103
constexpr HybridTreePath()
Default constructor.
Definition: treepath.hh:87
constexpr auto operator[](Dune::index_constant< i >) const
Get the index value at position pos.
Definition: treepath.hh:121
constexpr auto element(Dune::index_constant< i > pos={}) const
Get the last index value.
Definition: treepath.hh:139
constexpr HybridTreePath(const HybridTreePath &tp)=default
constexpr std::size_t operator[](std::size_t pos) const
Get the index value at position pos.
Definition: treepath.hh:127
auto back() const
Get the last index value.
Definition: treepath.hh:156
constexpr static index_sequence enumerate()
Returns an index_sequence for enumerating the components of this HybridTreePath.
Definition: treepath.hh:108
constexpr HybridTreePath & operator=(const HybridTreePath &tp)=default
std::index_sequence_for< T... > index_sequence
An index_sequence for the entries in this HybridTreePath.
Definition: treepath.hh:84
Definition: treepath.hh:34
Definition: treepath.hh:37
Definition: treepath.hh:40
Definition: treepath.hh:43
Definition: treepath.hh:46
Definition: treepath.hh:49
Definition: treepath.hh:52
Definition: treepath.hh:55
HybridTreePath< index_constant< i >..., index_constant< k > > type
Definition: treepath.hh:433
HybridTreePath< index_constant< k >, index_constant< i >... > type
Definition: treepath.hh:439
HybridTreePath< index_constant< i >... > type
Definition: treepath.hh:460
HybridTreePath< index_constant< i >... > type
Definition: treepath.hh:474
HybridTreePath< index_constant< i >..., index_constant< k >... > type
Definition: treepath.hh:480