6#ifndef DUNE_TYPETREE_HYBRIDMULTIINDEX_HH
7#define DUNE_TYPETREE_HYBRIDMULTIINDEX_HH
14#include <dune/common/typetraits.hh>
15#include <dune/common/indices.hh>
16#include <dune/common/hybridutilities.hh>
24 constexpr bool isHybridSizeT()
26 if constexpr (std::is_same_v<T, std::size_t>)
30 if constexpr (
requires { T::value; })
31 return std::is_same_v<T, std::integral_constant<std::size_t, T::value>>;
38 constexpr auto castToHybridSizeT(T t)
40 if constexpr (Dune::IsIntegralConstant<T>::value)
42 using VT =
typename T::value_type;
44 std::is_convertible_v<VT,std::size_t> &&
45 std::is_integral_v<VT> &&
47 "HybridMultiIndex indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
48 return std::integral_constant<std::size_t, T::value>{};
50 if constexpr (std::is_integral_v<T>)
53 std::is_convertible_v<T,std::size_t> &&
54 std::is_integral_v<T>,
55 "HybridMultiIndex indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
57 "HybridMultiIndex indices must be convertible to std::size_t or std::integral_constant<std::size_t,v>");
58 return std::size_t(t);
60 if constexpr (not (Dune::IsIntegralConstant<T>::value or std::is_integral_v<T>))
62 return std::size_t(0);
79 template<
typename... T>
84 static_assert((... && Impl::isHybridSizeT<T>()),
85 "HybridMultiIndex index storage must be std::size_t or std::integral_constant<std::size_t,v>");
108 template<
typename... I>
109 requires ((
sizeof...(T) > 0 &&
sizeof...(I) ==
sizeof...(T))
110 and ((std::is_integral_v<I> or Dune::IsIntegralConstant<I>::value) && ...))
112 : _data(Impl::castToHybridSizeT(i)...)
122 [[nodiscard]]
constexpr static std::size_t
size()
128 [[nodiscard]]
constexpr static std::size_t
max_size()
139 template<std::
size_t i>
140 requires (
sizeof...(T) > i)
141 [[nodiscard]]
constexpr auto get()
const
143 return std::get<i>(_data);
147 template<std::
size_t i>
148 requires (
sizeof...(T) > i)
149 [[nodiscard]]
constexpr auto operator[](Dune::index_constant<i>)
const
151 return std::get<i>(_data);
155 [[nodiscard]]
constexpr std::size_t
operator[](std::size_t pos)
const
157 std::size_t entry = 0;
158 Dune::Hybrid::forEach(
enumerate(), [&] (
auto i) {
166 template<std::
size_t i>
167 requires (
sizeof...(T) > i)
168 [[deprecated(
"Method will be removed after Dune 2.11. Use operator[] instead.")]]
169 [[nodiscard]]
constexpr auto element(Dune::index_constant<i> pos = {})
const
171 return std::get<i>(_data);
175 [[deprecated(
"Method will be removed after Dune 2.11. Use operator[] instead.")]]
176 [[nodiscard]]
constexpr std::size_t
element(std::size_t pos)
const
178 std::size_t entry = 0;
179 Dune::Hybrid::forEach(
enumerate(), [&] (
auto i) {
187 template<std::size_t n =
sizeof...(T)>
188 requires (n > 0 && n ==
sizeof...(T))
189 [[nodiscard]]
constexpr auto front()
const
191 return std::get<0>(_data);
195 template<std::size_t n =
sizeof...(T)>
196 requires (n > 0 && n ==
sizeof...(T))
197 [[nodiscard]]
constexpr auto back()
const
199 return std::get<n-1>(_data);
204 template<
class... Head,
class... Other>
207 std::tuple<T...> _data;
211 template<
typename... I>
212 requires (((std::is_integral_v<I> or Dune::IsIntegralConstant<I>::value) && ...))
213 HybridMultiIndex(I... i) -> HybridMultiIndex<
decltype(Impl::castToHybridSizeT(i))...>;
215 template<
typename... I>
216 HybridMultiIndex(std::tuple<I...>) -> HybridMultiIndex<I...>;
224 template<
typename... T>
225 [[nodiscard]]
constexpr auto back(
const HybridMultiIndex<T...>& tp)
226 ->
decltype(tp.back())
237 template<
typename... T>
238 [[nodiscard]]
constexpr auto front(
const HybridMultiIndex<T...>& tp)
239 ->
decltype(tp.front())
248 template<
typename... T>
249 [[nodiscard]]
constexpr HybridMultiIndex<T...,std::size_t> push_back(
const HybridMultiIndex<T...>& tp, std::size_t i)
251 return unpackIntegerSequence([&](
auto... j){
252 return HybridMultiIndex(tp[j] ..., i);
271 template<std::size_t i,
typename... T>
272 [[nodiscard]]
constexpr HybridMultiIndex<T...,index_constant<i>> push_back(
const HybridMultiIndex<T...>& tp, index_constant<i> iConstant = {})
274 return unpackIntegerSequence([&](
auto... j){
275 return HybridMultiIndex(tp[j] ..., iConstant);
283 template<
typename... T>
284 [[nodiscard]]
constexpr HybridMultiIndex<std::size_t,T...> push_front(
const HybridMultiIndex<T...>& tp, std::size_t i)
286 return unpackIntegerSequence([&](
auto... j){
287 return HybridMultiIndex(i, tp[j] ...);
306 template<std::size_t i,
typename... T>
307 [[nodiscard]]
constexpr HybridMultiIndex<index_constant<i>,T...> push_front(
const HybridMultiIndex<T...>& tp, index_constant<i> iConstant = {})
309 return unpackIntegerSequence([&](
auto... j){
310 return HybridMultiIndex(iConstant, tp[j] ...);
326 template<
typename I,
typename... T>
327 requires (
sizeof...(T) > 0)
328 [[nodiscard]]
constexpr auto accumulate_back(
const HybridMultiIndex<T...>& tp, I i) {
329 using ::Dune::Hybrid::plus;
330 return push_back(pop_back(tp), plus(back(tp), i));
346 template<
typename I,
typename... T>
347 requires (
sizeof...(T) > 0)
348 [[nodiscard]]
constexpr auto accumulate_front(
const HybridMultiIndex<T...>& tp, I i) {
349 using ::Dune::Hybrid::plus;
350 return push_front(pop_front(tp), plus(front(tp), i));
354 template<
class... Head,
class... Other>
355 [[nodiscard]]
constexpr auto join(
const HybridMultiIndex<Head...>& head,
const Other&... tail) {
361 [[nodiscard]]
constexpr auto reverse(
const HybridMultiIndex<T...>& tp) {
362 constexpr std::size_t size =
sizeof...(T);
363 return unpackIntegerSequence([&](
auto... i){
364 return HybridMultiIndex(tp[index_constant<size-i-1>{}] ...);
365 }, std::make_index_sequence<size>{});
372 template <
class... T>
373 requires (
sizeof...(T) > 0)
374 [[nodiscard]]
constexpr auto pop_front(
const HybridMultiIndex<T...>& tp)
376 return unpackIntegerSequence([&](
auto... i){
377 return HybridMultiIndex{std::make_tuple(tp[Dune::index_constant<i+1>{}]...)};
378 }, std::make_index_sequence<(
sizeof...(T) - 1)>{});
385 template <
class... T>
386 requires (
sizeof...(T) > 0)
387 [[nodiscard]]
constexpr auto pop_back(
const HybridMultiIndex<T...>& tp)
389 return unpackIntegerSequence([&](
auto... i){
390 return HybridMultiIndex{std::make_tuple(tp[i]...)};
391 }, std::make_index_sequence<(
sizeof...(T) - 1)>{});
403 template <
class... S,
class... T>
404 [[nodiscard]]
constexpr bool operator==(
405 const HybridMultiIndex<S...>& lhs,
406 const HybridMultiIndex<T...>& rhs)
408 if constexpr (
sizeof...(S) ==
sizeof...(T)) {
409 if constexpr ((Dune::IsInteroperable<S,T>::value &&...)) {
410 return unpackIntegerSequence([&](
auto... i){
411 return ((lhs[i] == rhs[i]) &&...);
427 template <
class S, S... lhs,
class T, T... rhs>
428 [[nodiscard]]
constexpr auto operator==(
429 const HybridMultiIndex<std::integral_constant<S,lhs>...>&,
430 const HybridMultiIndex<std::integral_constant<T,rhs>...>&)
434 constexpr auto result = (HybridMultiIndex(lhs...) == HybridMultiIndex(rhs...));
435 return std::bool_constant<result>{};
440 template <
class... S,
class... T>
441 [[nodiscard]]
constexpr auto operator!=(
442 const HybridMultiIndex<S...>& lhs,
443 const HybridMultiIndex<T...>& rhs)
445 return !(lhs == rhs);
449 template <
class S, S... lhs,
class T, T... rhs>
450 [[nodiscard]]
constexpr auto operator!=(
451 const HybridMultiIndex<std::integral_constant<S,lhs>...>&,
452 const HybridMultiIndex<std::integral_constant<T,rhs>...>&)
456 constexpr auto result = (HybridMultiIndex(lhs...) != HybridMultiIndex(rhs...));
457 return std::bool_constant<result>{};
461 template<
typename... T>
462 std::ostream& operator<<(std::ostream& os,
const HybridMultiIndex<T...>& tp)
464 os <<
"HybridMultiIndex< ";
465 Dune::Hybrid::forEach(tp, [&] (
auto tp_i) {
479 template<
typename... T>
480 struct tuple_size<Dune::HybridMultiIndex<T...>> :
public std::integral_constant<std::size_t,sizeof...(T)> {};
482 template <
size_t i,
typename... T>
483 struct tuple_element<i, Dune::HybridMultiIndex<T...> >
485 using type = std::tuple_element_t<i, std::tuple<T...> >;
A hybrid multi-index class that supports both compile time and run time indices.
Definition: hybridmultiindex.hh:81
static constexpr std::size_t size()
Get the size (length) of this multi-index.
Definition: hybridmultiindex.hh:122
constexpr auto operator[](Dune::index_constant< i >) const
Get the index value at position pos.
Definition: hybridmultiindex.hh:149
static constexpr std::size_t max_size()
Get the size (length) of this multi-index.
Definition: hybridmultiindex.hh:128
constexpr auto front() const
Get the first index value. Only available in non-empty multi-indices.
Definition: hybridmultiindex.hh:189
static constexpr index_sequence enumerate()
Returns an index_sequence for enumerating the components of this HybridMultiIndex.
Definition: hybridmultiindex.hh:116
constexpr auto get() const
Get the index value at position pos.
Definition: hybridmultiindex.hh:141
constexpr HybridMultiIndex(std::tuple< T... > t)
Constructor from a std::tuple
Definition: hybridmultiindex.hh:103
constexpr auto back() const
Get the last index value. Only available in non-empty multi-indices.
Definition: hybridmultiindex.hh:197
constexpr auto element(Dune::index_constant< i > pos={}) const
Get the last index value.
Definition: hybridmultiindex.hh:169
std::index_sequence_for< T... > index_sequence
An index_sequence for the entries in this HybridMultiIndex.
Definition: hybridmultiindex.hh:90
constexpr std::size_t operator[](std::size_t pos) const
Get the index value at position pos.
Definition: hybridmultiindex.hh:155
constexpr HybridMultiIndex(I... i)
Constructor from arguments.
Definition: hybridmultiindex.hh:111
constexpr std::size_t element(std::size_t pos) const
Get the index value at position pos.
Definition: hybridmultiindex.hh:176