3#ifndef DUNE_FUNCTIONS_COMMON_INDEX_ACCESS_HH
4#define DUNE_FUNCTIONS_COMMON_INDEX_ACCESS_HH
10#include <dune/common/typetraits.hh>
11#include <dune/common/concept.hh>
12#include <dune/common/hybridutilities.hh>
26template<
class size_type>
27struct HasDynamicIndexAccess
30 auto require(C&& c) ->
decltype(
31 c[std::declval<size_type>()]
35struct HasStaticIndexAccess
38 auto require(C&& c) ->
decltype(
61template<
class C,
class I,
class F,
62 typename std::enable_if< Dune::models<Imp::Concept::HasDynamicIndexAccess<I>, C>(),
int>::type = 0>
86template<
class C,
class I,
class F,
87 typename std::enable_if< not Dune::models<Imp::Concept::HasDynamicIndexAccess<I>, C>(),
int>::type = 0>
90 using Size =
decltype(Hybrid::size(c));
91 return Hybrid::switchCases(std::make_index_sequence<Size::value>(), i,
92 [&](
const auto& ii) ->
decltype(
auto){
94 }, [&]() ->
decltype(
auto){
95 return f(c[Dune::Indices::_0]);
115 template<
class Index, std::
size_t offset=1>
116 class ShiftedDynamicMultiIndex
119 ShiftedDynamicMultiIndex(
const Index& index) :
123 std::size_t operator[](std::size_t position)
const
126 return index_[position+offset];
134 ShiftedDynamicMultiIndex<Index, offset+1> pop()
const
139 std::size_t size()
const
141 if (offset < index_.size())
142 return index_.size() - offset;
151 template<
class Index, std::
size_t offset=1>
152 class ShiftedStaticMultiIndex
155 ShiftedStaticMultiIndex(
const Index& index) :
159 template<std::
size_t i>
160 auto operator[](Dune::index_constant<i>)
const
162 if constexpr (i<size()) {
163 return index_[Dune::index_constant<i+offset>{}];
165 return Dune::index_constant<0>{};
172 ShiftedStaticMultiIndex<Index, offset+1> pop()
const
177 static constexpr std::size_t size()
179 auto fullSize =
decltype(Hybrid::size(std::declval<Index>()))::value;
180 if (offset < fullSize)
181 return fullSize - offset;
195 template<std::
size_t offset,
class Index>
196 ShiftedDynamicMultiIndex<Index, offset> shiftedDynamicMultiIndex(
const Index& index)
201 template<std::
size_t offset,
class Index>
202 ShiftedStaticMultiIndex<Index, offset> shiftedStaticMultiIndex(
const Index& index)
214template<
class Result,
class Index>
215struct MultiIndexResolver
217 MultiIndexResolver(
const Index& index) :
222 typename std::enable_if<not std::is_convertible<C&, Result>::value,
int>::type = 0>
223 Result operator()(C&& c)
225 auto&& subIndex = Imp::shiftedDynamicMultiIndex<1>(index_);
226 auto&& subIndexResolver = MultiIndexResolver<Result, decltype(subIndex)>(subIndex);
227 return (Result)(
hybridIndexAccess(c, index_[Dune::Indices::_0], subIndexResolver));
231 typename std::enable_if<std::is_convertible<C&, Result>::value,
int>::type = 0>
232 Result operator()(C&& c)
234 return (Result)(std::forward<C>(c));
262template<
class Result,
class C,
class MultiIndex>
266 Imp::MultiIndexResolver<Result, MultiIndex> multiIndexResolver(index);
267 return multiIndexResolver(c);
277 template<
class C,
class MultiIndex,
class IsFinal>
282 return Hybrid::ifElse(isFinal(c), [&, c =
forwardCapture(std::forward<C>(c))](
auto) ->
decltype(
auto) {
283 assert(multiIndex.size() == 0);
285 }, [&](
auto) ->
decltype(
auto) {
286 auto hasDynamicAccess =
callableCheck([](
auto&& cc) -> std::void_t<
decltype(cc[0])> {});
289 auto i = multiIndex[0];
290 auto tail = multiIndex.pop();
297 return Hybrid::ifElse(hasDynamicAccess(c), [&](
auto id) ->
decltype(
auto) {
299 }, [&](
auto id) ->
decltype(
auto) {
301 auto indexRange =
typename decltype(range(Hybrid::size(
id(c))))::integer_sequence();
302 return Hybrid::switchCases(indexRange, i, [&](
auto static_i) ->
decltype(
auto){
305 }, [&]() ->
decltype(
auto){
313 template<
class C,
class MultiIndex>
316 auto isExhausted = Hybrid::equals(Hybrid::size(multiIndex), Dune::Indices::_0);
317 return Hybrid::ifElse(isExhausted, [&, c =
forwardCapture(std::forward<C>(c))](
auto) ->
decltype(
auto) {
319 }, [&](
auto id) ->
decltype(
auto) {
320 auto head = multiIndex[Dune::Indices::_0];
321 auto tail = multiIndex.pop();
353template<
class C,
class MultiIndex,
class IsFinal>
375template<
class C,
class MultiIndex>
397template<
class C,
class MultiIndex>
auto hybridIndexAccess(C &&c, const I &i, F &&f) -> decltype(f(c[i]))
Provide operator[] index-access for containers.
Definition: indexaccess.hh:63
constexpr decltype(auto) resolveStaticMultiIndex(C &&c, const MultiIndex &multiIndex)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:398
auto callableCheck(Expression f)
Create a predicate for checking validity of expressions.
Definition: utility.hh:279
constexpr decltype(auto) resolveDynamicMultiIndex(C &&c, const MultiIndex &multiIndex)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:376
constexpr decltype(auto) resolveDynamicMultiIndex(C &&c, const MultiIndex &multiIndex, const IsFinal &isFinal)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:354
Result hybridMultiIndexAccess(C &&c, const MultiIndex &index)
Provide multi-index access by chaining operator[].
Definition: indexaccess.hh:263
auto negatePredicate(Check check)
Negate given predicate.
Definition: utility.hh:304
Definition: polynomial.hh:10
auto forwardCapture(T &&t)
Create a capture object for perfect forwarding.
Definition: utility.hh:372