DUNE PDELab (git)

treepath.hh
1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=8 sw=2 sts=2:
3 // SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-GPL-2.0-only-with-PDELab-exception
5 
6 #ifndef DUNE_TYPETREE_TREEPATH_HH
7 #define DUNE_TYPETREE_TREEPATH_HH
8 
9 #include <cstddef>
10 #include <cassert>
11 #include <iostream>
12 #include <type_traits>
13 
15 #include <dune/common/version.hh>
17 #include <dune/common/indices.hh>
18 #include <dune/common/hybridutilities.hh>
19 #include <dune/common/typelist.hh>
20 
21 #include <dune/typetree/fixedcapacitystack.hh>
22 #include <dune/typetree/utility.hh>
23 
24 namespace Dune {
25  namespace TypeTree {
26 
27  // The Impl namespace collects some free standing functions helper functions
28  namespace Impl {
29  template<typename T>
30  struct check_size_t_impl
31  {
32  static constexpr auto check() {
33  return std::is_same_v<T, std::size_t>;
34  }
35  };
36 
37  template<class T, T v>
38  struct check_size_t_impl<std::integral_constant<T,v>>
39  {
40  static constexpr auto check() {
41  return std::is_same_v<T, std::size_t>;
42  }
43  };
44 
45  template<typename T>
46  constexpr auto check_size_t() {
47  return check_size_t_impl<T>::check();
48  }
49 
50  template<typename T>
51  constexpr auto cast_size_t(const T & v) {
52  // check that T is an integral type that can be cast to std::size_t
53  static_assert(
54  std::is_convertible_v<T,std::size_t> &&
55  std::is_integral_v<T>,
56  "HybridTreePath indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
57  // positivity can only be checked at run-time
58  assert(v >= 0 &&
59  "HybridTreePath indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
60  return std::size_t(v);
61  }
62 
63  template<class T, T v>
64  constexpr auto cast_size_t(std::integral_constant<T,v>) {
65  // check that T is an intergal type that can be cast to std::size_t
66  // and that v is positive
67  static_assert(
68  std::is_convertible_v<T,std::size_t> &&
69  std::is_integral_v<T> &&
70  v >= 0,
71  "HybridTreePath indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
72  return std::integral_constant<std::size_t,v>();
73  }
74 
75  // these are helper functions that help triggering a deprecation warning
76  template<typename T>
77  [[deprecated("HybridTreePath index storage should be std::size_t or std::integral_constant<std::size_t,v>!\n"
78  "Using anything else is deprecated and will not possible after the 2.10 release.\n"
79  "It is adviced not to specify the template parameters expicitly,\n"
80  "but to use the helper functions `hybridTreePath` or `treePath`."
81  "These take care of converting indices to the appropriate storage.")]]
82  constexpr bool check_storage_type(MetaType<T>) {
83  return false;
84  }
85 
86  // specialization of valid index type
87  template<std::size_t v>
88  constexpr bool check_storage_type(MetaType<std::integral_constant<std::size_t,v>>) {
89  return true;
90  }
91 
92  // specialization of valid index type
93  constexpr bool check_storage_type(MetaType<std::size_t>) {
94  return true;
95  }
96  }
97 
98  template<typename... T>
99  class HybridTreePath;
100 
104 
105  namespace TreePathType {
106  enum Type { fullyStatic, dynamic };
107  }
108 
109  template<typename>
110  struct TreePathSize;
111 
112  template<typename,std::size_t>
113  struct TreePathPushBack;
114 
115  template<typename,std::size_t>
116  struct TreePathPushFront;
117 
118  template<typename>
119  struct TreePathBack;
120 
121  template<typename>
122  struct TreePathFront;
123 
124  template<typename, std::size_t...>
125  struct TreePathPopBack;
126 
127  template<typename>
128  struct TreePathPopFront;
129 
130  template<typename, typename>
131  struct TreePathConcat;
132 
133  template<std::size_t... i>
134  void print_tree_path(std::ostream& os)
135  {}
136 
137  template<std::size_t k, std::size_t... i>
138  void print_tree_path(std::ostream& os)
139  {
140  os << k << " ";
141  print_tree_path<i...>(os);
142  }
143 
145 
156  template<typename... T>
158  {
159 
160  // enable check for dune-typetree 2.10 and above
161 #if DUNE_VERSION_GTE(TYPETREE,2,10)
162  // make sure that all indices use std::size_t as the underlying number type
163  static_assert((... && Impl::check_size_t<T>()),
164  "HybridTreePath index storage must be std::size_t or std::integral_constant<std::size_t,v>");
165 #endif
166 
167  public:
168 
170  using index_sequence = std::index_sequence_for<T...>;
171 
173  constexpr HybridTreePath()
174  {
175  [[maybe_unused]] constexpr bool check =
176  (... && Impl::check_storage_type(MetaType<T>()) );
177  }
178 
179  constexpr HybridTreePath(const HybridTreePath& tp) = default;
180  constexpr HybridTreePath(HybridTreePath&& tp) = default;
181 
182  constexpr HybridTreePath& operator=(const HybridTreePath& tp) = default;
183  constexpr HybridTreePath& operator=(HybridTreePath&& tp) = default;
184 
186  explicit constexpr HybridTreePath(std::tuple<T...> t)
187  : _data(t)
188  {
189  [[maybe_unused]] constexpr bool check =
190  (... && Impl::check_storage_type(MetaType<T>()) );
191  }
192 
194  template<typename... U,
195  typename std::enable_if_t<(sizeof...(T) > 0 && sizeof...(U) == sizeof...(T)),bool> = true>
196  explicit constexpr HybridTreePath(U... t)
197  : _data(t...) // we assume that all arguments are convertible to the types T...
198  {
199  [[maybe_unused]] constexpr bool check =
200  (... && Impl::check_storage_type(MetaType<T>()) );
201  }
202 
204  [[nodiscard]] constexpr static index_sequence enumerate()
205  {
206  return {};
207  }
208 
210  [[nodiscard]] constexpr static std::size_t size()
211  {
212  return sizeof...(T);
213  }
214 
216  [[nodiscard]] constexpr static std::size_t max_size()
217  {
218  return size();
219  }
220 
222  template<std::size_t i,
223  std::enable_if_t<(sizeof...(T) > i),bool> = true>
224  [[nodiscard]] constexpr auto operator[](Dune::index_constant<i>) const
225  {
226  return std::get<i>(_data);
227  }
228 
230  [[nodiscard]] constexpr std::size_t operator[](std::size_t pos) const
231  {
232  std::size_t entry = 0;
233  Dune::Hybrid::forEach(enumerate(), [&] (auto i) {
234  if (i==pos)
235  entry = this->element(i);
236  });
237  return entry;
238  }
239 
241  template<std::size_t i,
242  std::enable_if_t<(sizeof...(T) > i),bool> = true>
243  [[nodiscard]] constexpr auto element(Dune::index_constant<i> pos = {}) const
244  {
245  return std::get<i>(_data);
246  }
247 
249  [[nodiscard]] constexpr std::size_t element(std::size_t pos) const
250  {
251  std::size_t entry = 0;
252  Dune::Hybrid::forEach(enumerate(), [&] (auto i) {
253  if (i==pos)
254  entry = this->element(i);
255  });
256  return entry;
257  }
258 
260  template<std::size_t n = sizeof...(T),
261  std::enable_if_t<(n > 0 && n == sizeof...(T)),bool> = true>
262  [[nodiscard]] constexpr auto front() const
263  {
264  return std::get<0>(_data);
265  }
266 
268  template<std::size_t n = sizeof...(T),
269  std::enable_if_t<(n > 0 && n == sizeof...(T)),bool> = true>
270  [[nodiscard]] constexpr auto back() const
271  {
272  return std::get<n-1>(_data);
273  }
274 
275 #ifndef DOXYGEN
276 
277  // I can't be bothered to make all the external accessors friends of HybridTreePath,
278  // so we'll only hide the data tuple from the user in Doxygen.
279 
280  using Data = std::tuple<T...>;
281  Data _data;
282 
283 #endif // DOXYGEN
284 
285  };
286 
288 
294  template<typename... T>
295  [[nodiscard]] constexpr auto makeTreePath(const T... t)
296  {
297  // check that all entries are based on std::size_t
298  static_assert((... && Impl::check_size_t<T>()),
299  "HybridTreePath indices must be of type std::size_t or std::integral_constant<std::size_t,v>");
300  return HybridTreePath<T...>(t...);
301  }
302 
304 
311  template<typename... T>
312  [[nodiscard]] constexpr auto hybridTreePath(const T&... t)
313  {
314  return makeTreePath(Impl::cast_size_t(t)...);
315  }
316 
318 
325  template<typename... T>
326  [[nodiscard]] constexpr auto treePath(const T&... t)
327  {
328  return makeTreePath(Impl::cast_size_t(t)...);
329  }
330 
331 
333  template<typename... T>
334  [[nodiscard]] constexpr std::size_t treePathSize(const HybridTreePath<T...>&)
335  {
336  return sizeof...(T);
337  }
338 
340 
356  template<std::size_t i, typename... T>
357  [[nodiscard]] constexpr auto treePathEntry(const HybridTreePath<T...>& tp, index_constant<i> = {})
358  -> typename std::decay<decltype(std::get<i>(tp._data))>::type
359  {
360  return std::get<i>(tp._data);
361  }
362 
364 
379  template<std::size_t i,typename... T>
380  [[nodiscard]] constexpr std::size_t treePathIndex(const HybridTreePath<T...>& tp, index_constant<i> = {})
381  {
382  return std::get<i>(tp._data);
383  }
384 
386 
391  template<typename... T>
392  [[nodiscard]] constexpr auto back(const HybridTreePath<T...>& tp)
393  -> decltype(tp.back())
394  {
395  return tp.back();
396  }
397 
399 
404  template<typename... T>
405  [[nodiscard]] constexpr auto front(const HybridTreePath<T...>& tp)
406  -> decltype(tp.front())
407  {
408  return tp.front();
409  }
410 
412 
415  template<typename... T>
416  [[nodiscard]] constexpr HybridTreePath<T...,std::size_t> push_back(const HybridTreePath<T...>& tp, std::size_t i)
417  {
418  return HybridTreePath<T...,std::size_t>(std::tuple_cat(tp._data,std::make_tuple(i)));
419  }
420 
422 
436  template<std::size_t i, typename... T>
437  [[nodiscard]] constexpr HybridTreePath<T...,index_constant<i>> push_back(const HybridTreePath<T...>& tp, index_constant<i> i_ = {})
438  {
439  return HybridTreePath<T...,index_constant<i> >(std::tuple_cat(tp._data,std::make_tuple(i_)));
440  }
441 
443 
446  template<typename... T>
447  [[nodiscard]] constexpr HybridTreePath<std::size_t,T...> push_front(const HybridTreePath<T...>& tp, std::size_t element)
448  {
449  return HybridTreePath<std::size_t,T...>(std::tuple_cat(std::make_tuple(element),tp._data));
450  }
451 
453 
467  template<std::size_t i, typename... T>
468  [[nodiscard]] constexpr HybridTreePath<index_constant<i>,T...> push_front(const HybridTreePath<T...>& tp, index_constant<i> _i = {})
469  {
470  return HybridTreePath<index_constant<i>,T...>(std::tuple_cat(std::make_tuple(_i),tp._data));
471  }
472 
474 
485  template<typename I, typename... T, std::enable_if_t<(sizeof...(T) > 0),bool> = true>
486  [[nodiscard]] constexpr auto accumulate_back(const HybridTreePath<T...>& tp, I i) {
488  return push_back(pop_back(tp), plus(back(tp), i));
489  }
490 
491 
493 
504  template<typename I, typename... T, std::enable_if_t<(sizeof...(T) > 0),bool> = true>
505  [[nodiscard]] constexpr auto accumulate_front(const HybridTreePath<T...>& tp, I i) {
507  return push_front(pop_front(tp), plus(front(tp), i));
508  }
509 
511  template<class... Head, class... Other>
512  [[nodiscard]] constexpr auto join(const HybridTreePath<Head...>& head, const Other&... tail) {
513  return TypeTree::HybridTreePath{std::tuple_cat(head._data, tail._data...)};
514  }
515 
517  template<class... T>
518  [[nodiscard]] constexpr auto reverse(const HybridTreePath<T...>& tp) {
519  constexpr std::size_t size = sizeof...(T);
520  return unpackIntegerSequence([&](auto... i){
521  return treePath(tp[index_constant<size-i-1>{}] ...);
522  }, std::make_index_sequence<size>{});
523  }
524 
526 
529  template <class... T, std::enable_if_t<(sizeof...(T) > 0),bool> = true>
530  [[nodiscard]] constexpr auto pop_front(const HybridTreePath<T...>& tp)
531  {
532  return unpackIntegerSequence([&](auto... i){
533  return HybridTreePath{std::make_tuple(std::get<i+1>(tp._data)...)};
534  }, std::make_index_sequence<(sizeof...(T) - 1)>{});
535  }
536 
538 
541  template <class... T, std::enable_if_t<(sizeof...(T) > 0),bool> = true>
542  [[nodiscard]] constexpr auto pop_back(const HybridTreePath<T...>& tp)
543  {
544  return unpackIntegerSequence([&](auto... i){
545  return HybridTreePath{std::make_tuple(std::get<i>(tp._data)...)};
546  }, std::make_index_sequence<(sizeof...(T) - 1)>{});
547  }
548 
550 
558  template <class... S, class... T>
559  [[nodiscard]] constexpr bool operator==(
560  const HybridTreePath<S...>& lhs,
561  const HybridTreePath<T...>& rhs)
562  {
563  if constexpr (sizeof...(S) == sizeof...(T)) {
564  if constexpr ((Dune::IsInteroperable<S,T>::value &&...)) {
565  return unpackIntegerSequence([&](auto... i){
566  return ((std::get<i>(lhs._data) == std::get<i>(rhs._data)) &&...);
567  }, std::make_index_sequence<(sizeof...(S))>{});
568  } else {
569  return false;
570  }
571  } else {
572  return false;
573  }
574  }
575 
577 
582  template <class S, S... lhs, class T, T... rhs>
583  [[nodiscard]] constexpr auto operator==(
584  const HybridTreePath<std::integral_constant<S,lhs>...>&,
585  const HybridTreePath<std::integral_constant<T,rhs>...>&)
586  {
587  return std::bool_constant<hybridTreePath(lhs...) == hybridTreePath(rhs...)>{};
588  }
589 
590 
592  template <class... S, class... T>
593  [[nodiscard]] constexpr auto operator!=(
594  const HybridTreePath<S...>& lhs,
595  const HybridTreePath<T...>& rhs)
596  {
597  return !(lhs == rhs);
598  }
599 
601  template <class S, S... lhs, class T, T... rhs>
602  [[nodiscard]] constexpr auto operator!=(
603  const HybridTreePath<std::integral_constant<S,lhs>...>&,
604  const HybridTreePath<std::integral_constant<T,rhs>...>&)
605  {
606  return std::bool_constant<hybridTreePath(lhs...) != hybridTreePath(rhs...)>{};
607  }
608 
609 
610  inline namespace Literals {
611 
613 
617  template <char... digits>
618  constexpr auto operator"" _tp()
619  {
620  using namespace Dune::Indices::Literals;
621  return hybridTreePath(operator""_ic<digits...>());
622  }
623 
624  } // end namespace Literals
625 
626 
627  template<std::size_t... i>
628  struct TreePathSize<HybridTreePath<index_constant<i>...> >
629  : public index_constant<sizeof...(i)>
630  {};
631 
632 
633  template<std::size_t k, std::size_t... i>
634  struct TreePathPushBack<HybridTreePath<index_constant<i>...>,k>
635  {
636  typedef HybridTreePath<index_constant<i>...,index_constant<k>> type;
637  };
638 
639  template<std::size_t k, std::size_t... i>
640  struct TreePathPushFront<HybridTreePath<index_constant<i>...>,k>
641  {
642  typedef HybridTreePath<index_constant<k>,index_constant<i>...> type;
643  };
644 
645  template<std::size_t k>
646  struct TreePathBack<HybridTreePath<index_constant<k>>>
647  : public index_constant<k>
648  {};
649 
650  template<std::size_t j, std::size_t k, std::size_t... l>
651  struct TreePathBack<HybridTreePath<index_constant<j>,index_constant<k>,index_constant<l>...>>
652  : public TreePathBack<HybridTreePath<index_constant<k>,index_constant<l>...>>
653  {};
654 
655  template<std::size_t k, std::size_t... i>
656  struct TreePathFront<HybridTreePath<index_constant<k>,index_constant<i>...>>
657  : public index_constant<k>
658  {};
659 
660  template<std::size_t k, std::size_t... i>
661  struct TreePathPopBack<HybridTreePath<index_constant<k>>,i...>
662  {
663  typedef HybridTreePath<index_constant<i>...> type;
664  };
665 
666  template<std::size_t j,
667  std::size_t k,
668  std::size_t... l,
669  std::size_t... i>
670  struct TreePathPopBack<HybridTreePath<index_constant<j>,index_constant<k>,index_constant<l>...>,i...>
671  : public TreePathPopBack<HybridTreePath<index_constant<k>,index_constant<l>...>,i...,j>
672  {};
673 
674  template<std::size_t k, std::size_t... i>
675  struct TreePathPopFront<HybridTreePath<index_constant<k>,index_constant<i>...> >
676  {
677  typedef HybridTreePath<index_constant<i>...> type;
678  };
679 
680  template<std::size_t... i, std::size_t... k>
681  struct TreePathConcat<HybridTreePath<index_constant<i>...>,HybridTreePath<index_constant<k>...> >
682  {
683  typedef HybridTreePath<index_constant<i>...,index_constant<k>...> type;
684  };
685 
686 #ifndef DOXYGEN
687 
688  namespace impl {
689 
690  // end of recursion
691  template<std::size_t i, typename... T>
692  typename std::enable_if<
693  (i == sizeof...(T))
694  >::type
695  print_hybrid_tree_path(std::ostream& os, const HybridTreePath<T...>& tp, index_constant<i> _i)
696  {}
697 
698  // print current entry and recurse
699  template<std::size_t i, typename... T>
700  typename std::enable_if<
701  (i < sizeof...(T))
702  >::type
703  print_hybrid_tree_path(std::ostream& os, const HybridTreePath<T...>& tp, index_constant<i> _i)
704  {
705  os << treePathIndex(tp,_i) << " ";
706  print_hybrid_tree_path(os,tp,index_constant<i+1>{});
707  }
708 
709  } // namespace impl
710 
711 #endif // DOXYGEN
712 
714  template<typename... T>
715  std::ostream& operator<<(std::ostream& os, const HybridTreePath<T...>& tp)
716  {
717  os << "HybridTreePath< ";
718  impl::print_hybrid_tree_path(os, tp, index_constant<0>{});
719  os << ">";
720  return os;
721  }
722 
723  template<std::size_t... i>
724  using StaticTreePath = HybridTreePath<Dune::index_constant<i>...>;
725 
727 
728  } // namespace TypeTree
729 } //namespace Dune
730 
731 #endif // DUNE_TYPETREE_TREEPATH_HH
A hybrid version of TreePath that supports both compile time and run time indices.
Definition: treepath.hh:158
constexpr auto back() const
Get the last index value. Only available in non-empty paths.
Definition: treepath.hh:270
constexpr std::size_t element(std::size_t pos) const
Get the index value at position pos.
Definition: treepath.hh:249
constexpr HybridTreePath(std::tuple< T... > t)
Constructor from a std::tuple
Definition: treepath.hh:186
constexpr static std::size_t size()
Get the size (length) of this path.
Definition: treepath.hh:210
constexpr HybridTreePath(U... t)
Constructor from arguments.
Definition: treepath.hh:196
constexpr HybridTreePath()
Default constructor.
Definition: treepath.hh:173
constexpr auto element(Dune::index_constant< i > pos={}) const
Get the last index value.
Definition: treepath.hh:243
constexpr auto operator[](Dune::index_constant< i >) const
Get the index value at position pos.
Definition: treepath.hh:224
constexpr static std::size_t max_size()
Get the size (length) of this path.
Definition: treepath.hh:216
constexpr auto front() const
Get the first index value. Only available in non-empty paths.
Definition: treepath.hh:262
constexpr std::size_t operator[](std::size_t pos) const
Get the index value at position pos.
Definition: treepath.hh:230
constexpr static index_sequence enumerate()
Returns an index_sequence for enumerating the components of this HybridTreePath.
Definition: treepath.hh:204
std::index_sequence_for< T... > index_sequence
An index_sequence for the entries in this HybridTreePath.
Definition: treepath.hh:170
Documentation related stuff.
Traits for type conversions and type information.
decltype(auto) constexpr unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition: indices.hh:124
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:29
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
constexpr auto plus
Function object for performing addition.
Definition: hybridutilities.hh:528
EnableIfInterOperable< T1, T2, bool >::type operator!=(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for inequality.
Definition: iteratorfacades.hh:259
EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:237
constexpr std::size_t treePathSize(const HybridTreePath< T... > &)
Returns the size (number of components) of the given HybridTreePath.
Definition: treepath.hh:334
constexpr auto accumulate_front(const HybridTreePath< T... > &tp, I i)
Hybrid utility that accumulates to the front of a multi-index.
Definition: treepath.hh:505
constexpr auto pop_front(const HybridTreePath< T... > &tp)
Removes first index on a HybridTreePath.
Definition: treepath.hh:530
constexpr auto reverse(const HybridTreePath< T... > &tp)
Reverses the order of the elements in the path.
Definition: treepath.hh:518
constexpr auto accumulate_back(const HybridTreePath< T... > &tp, I i)
Hybrid utility that accumulates to the back of a multi-index.
Definition: treepath.hh:486
constexpr auto join(const HybridTreePath< Head... > &head, const Other &... tail)
Join two tree paths into one.
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:357
constexpr auto pop_back(const HybridTreePath< T... > &tp)
Removes last index on a HybridTreePath.
Definition: treepath.hh:542
constexpr auto hybridTreePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:312
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:380
constexpr auto makeTreePath(const T... t)
helper function to construct a new HybridTreePath from the given indices.
Definition: treepath.hh:295
constexpr auto treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:326
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integer_sequence< T, II... > tail(std::integer_sequence< T, I0, II... >)
For a sequence [head,tail...) return the tail sequence.
Definition: integersequence.hh:58
constexpr std::integral_constant< T, I0 > front(std::integer_sequence< T, I0, II... >)
Return the first entry of the sequence.
Definition: integersequence.hh:39
constexpr std::integral_constant< T, I0 > head(std::integer_sequence< T, I0, II... >)
For a sequence [head,tail...) return the single head element.
Definition: integersequence.hh:53
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
constexpr std::integer_sequence< T, II..., T(IN)> push_back(std::integer_sequence< T, II... >, std::integral_constant< T, IN >={})
Append an index IN to the back of the sequence.
Definition: integersequence.hh:69
constexpr auto back(std::integer_sequence< T, II... > seq)
Return the last entry of the sequence.
Definition: integersequence.hh:44
constexpr std::integer_sequence< T, T(I0), II... > push_front(std::integer_sequence< T, II... >, std::integral_constant< T, I0 >={})
Append an index I0 to the front of the sequence.
Definition: integersequence.hh:64
Checks whether two types are interoperable.
Definition: typetraits.hh:65
A type that refers to another type.
Definition: typelist.hh:33
Various macros to work with Dune module version numbers.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)