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>
26 template<
class size_type>
27 struct HasDynamicIndexAccess
30 auto require(C&& c) -> decltype(
31 c[std::declval<size_type>()]
35 struct HasStaticIndexAccess
38 auto require(C&& c) -> decltype(
61 template<
class C,
class I,
class F,
62 typename std::enable_if< Dune::models<Imp::Concept::HasDynamicIndexAccess<I>, C>(),
int>::type = 0>
86 template<
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 auto isContained = Dune::Std::bool_constant<(i<size())>{};
163 return Hybrid::ifElse(isContained, [&](
auto id) {
164 return id(index_)[Dune::index_constant<i+offset>{}];
166 return Dune::Indices::_0;
173 ShiftedStaticMultiIndex<Index, offset+1> pop()
const
178 static constexpr std::size_t size()
180 auto fullSize = decltype(Hybrid::size(std::declval<Index>()))::value;
181 if (offset < fullSize)
182 return fullSize - offset;
196 template<std::
size_t offset,
class Index>
197 ShiftedDynamicMultiIndex<Index, offset> shiftedDynamicMultiIndex(
const Index& index)
202 template<std::
size_t offset,
class Index>
203 ShiftedStaticMultiIndex<Index, offset> shiftedStaticMultiIndex(
const Index& index)
215 template<
class Result,
class Index>
216 struct MultiIndexResolver
218 MultiIndexResolver(
const Index& index) :
223 typename std::enable_if<not std::is_convertible<C&, Result>::value,
int>::type = 0>
224 Result operator()(C&& c)
226 auto&& subIndex = Imp::shiftedDynamicMultiIndex<1>(index_);
227 auto&& subIndexResolver = MultiIndexResolver<Result, decltype(subIndex)>(subIndex);
228 return (Result)(
hybridIndexAccess(c, index_[Dune::Indices::_0], subIndexResolver));
232 typename std::enable_if<std::is_convertible<C&, Result>::value,
int>::type = 0>
233 Result operator()(C&& c)
235 return (Result)(std::forward<C>(c));
263 template<
class Result,
class C,
class MultiIndex>
267 Imp::MultiIndexResolver<Result, MultiIndex> multiIndexResolver(index);
268 return multiIndexResolver(c);
278 template<
class C,
class MultiIndex,
class IsFinal>
283 return Hybrid::ifElse(isFinal(c), [&, c =
forwardCapture(std::forward<C>(c))](
auto id) -> decltype(
auto) {
284 assert(multiIndex.size() == 0);
286 }, [&](
auto id) -> decltype(
auto) {
287 auto hasDynamicAccess =
callableCheck([](
auto&& cc) -> void_t<decltype(cc[0])> {});
290 auto i = multiIndex[0];
291 auto tail = multiIndex.pop();
298 return Hybrid::ifElse(hasDynamicAccess(c), [&](
auto id) -> decltype(
auto) {
300 }, [&](
auto id) -> decltype(
auto) {
302 auto indexRange =
typename decltype(range(Hybrid::size(
id(c))))::integer_sequence();
303 return Hybrid::switchCases(indexRange, i, [&](
auto static_i) -> decltype(
auto){
306 }, [&]() -> decltype(
auto){
314 template<
class C,
class MultiIndex>
317 auto isExhausted = Hybrid::equals(Hybrid::size(multiIndex), Dune::Indices::_0);
318 return Hybrid::ifElse(isExhausted, [&, c =
forwardCapture(std::forward<C>(c))](
auto id) -> decltype(
auto) {
320 }, [&](
auto id) -> decltype(
auto) {
321 auto head = multiIndex[Dune::Indices::_0];
322 auto tail = multiIndex.pop();
354 template<
class C,
class MultiIndex,
class IsFinal>
376 template<
class C,
class MultiIndex>
398 template<
class C,
class MultiIndex>
411 #endif // DUNE_FUNCTIONS_COMMON_INDEX_ACCESS_HH